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

Sign up to get free protection for your applications and to get access to all the features.
Files changed (175) 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/apple_gpu_stats +0 -0
  19. wandb/bin/wandb-core +0 -0
  20. wandb/cli/cli.py +131 -59
  21. wandb/data_types.py +6 -3
  22. wandb/docker/__init__.py +2 -2
  23. wandb/env.py +3 -3
  24. wandb/errors/term.py +10 -2
  25. wandb/filesync/step_checksum.py +1 -4
  26. wandb/filesync/step_prepare.py +4 -24
  27. wandb/filesync/step_upload.py +5 -107
  28. wandb/filesync/upload_job.py +0 -76
  29. wandb/integration/gym/__init__.py +35 -15
  30. wandb/integration/huggingface/resolver.py +2 -2
  31. wandb/integration/keras/callbacks/metrics_logger.py +1 -1
  32. wandb/integration/keras/keras.py +1 -1
  33. wandb/integration/openai/fine_tuning.py +21 -3
  34. wandb/integration/prodigy/prodigy.py +1 -1
  35. wandb/jupyter.py +16 -17
  36. wandb/old/summary.py +1 -1
  37. wandb/plot/confusion_matrix.py +1 -1
  38. wandb/plot/pr_curve.py +2 -1
  39. wandb/plot/roc_curve.py +2 -1
  40. wandb/{plots → plot}/utils.py +13 -25
  41. wandb/proto/v3/wandb_internal_pb2.py +54 -54
  42. wandb/proto/v3/wandb_settings_pb2.py +2 -2
  43. wandb/proto/v3/wandb_telemetry_pb2.py +10 -10
  44. wandb/proto/v4/wandb_internal_pb2.py +54 -54
  45. wandb/proto/v4/wandb_settings_pb2.py +2 -2
  46. wandb/proto/v4/wandb_telemetry_pb2.py +10 -10
  47. wandb/proto/v5/wandb_base_pb2.py +30 -0
  48. wandb/proto/v5/wandb_internal_pb2.py +355 -0
  49. wandb/proto/v5/wandb_server_pb2.py +63 -0
  50. wandb/proto/v5/wandb_settings_pb2.py +45 -0
  51. wandb/proto/v5/wandb_telemetry_pb2.py +41 -0
  52. wandb/proto/wandb_base_pb2.py +2 -0
  53. wandb/proto/wandb_deprecated.py +9 -1
  54. wandb/proto/wandb_generate_deprecated.py +34 -0
  55. wandb/proto/{wandb_internal_codegen.py → wandb_generate_proto.py} +1 -35
  56. wandb/proto/wandb_internal_pb2.py +2 -0
  57. wandb/proto/wandb_server_pb2.py +2 -0
  58. wandb/proto/wandb_settings_pb2.py +2 -0
  59. wandb/proto/wandb_telemetry_pb2.py +2 -0
  60. wandb/sdk/artifacts/artifact.py +68 -22
  61. wandb/sdk/artifacts/artifact_manifest.py +1 -1
  62. wandb/sdk/artifacts/artifact_manifest_entry.py +6 -3
  63. wandb/sdk/artifacts/artifact_manifests/artifact_manifest_v1.py +1 -1
  64. wandb/sdk/artifacts/artifact_saver.py +1 -10
  65. wandb/sdk/artifacts/storage_handlers/local_file_handler.py +6 -2
  66. wandb/sdk/artifacts/storage_handlers/multi_handler.py +1 -1
  67. wandb/sdk/artifacts/storage_handlers/tracking_handler.py +6 -4
  68. wandb/sdk/artifacts/storage_policies/wandb_storage_policy.py +2 -42
  69. wandb/sdk/artifacts/storage_policy.py +1 -12
  70. wandb/sdk/data_types/_dtypes.py +8 -8
  71. wandb/sdk/data_types/image.py +2 -2
  72. wandb/sdk/data_types/video.py +5 -3
  73. wandb/sdk/integration_utils/data_logging.py +5 -5
  74. wandb/sdk/interface/interface.py +14 -1
  75. wandb/sdk/interface/interface_shared.py +1 -1
  76. wandb/sdk/internal/file_pusher.py +2 -5
  77. wandb/sdk/internal/file_stream.py +6 -19
  78. wandb/sdk/internal/internal_api.py +148 -136
  79. wandb/sdk/internal/job_builder.py +208 -136
  80. wandb/sdk/internal/progress.py +0 -28
  81. wandb/sdk/internal/sender.py +102 -39
  82. wandb/sdk/internal/settings_static.py +8 -1
  83. wandb/sdk/internal/system/assets/trainium.py +3 -3
  84. wandb/sdk/internal/system/system_info.py +4 -2
  85. wandb/sdk/internal/update.py +1 -1
  86. wandb/sdk/launch/__init__.py +9 -1
  87. wandb/sdk/launch/_launch.py +4 -24
  88. wandb/sdk/launch/_launch_add.py +1 -3
  89. wandb/sdk/launch/_project_spec.py +187 -225
  90. wandb/sdk/launch/agent/agent.py +59 -19
  91. wandb/sdk/launch/agent/config.py +0 -3
  92. wandb/sdk/launch/builder/abstract.py +68 -1
  93. wandb/sdk/launch/builder/build.py +165 -576
  94. wandb/sdk/launch/builder/context_manager.py +235 -0
  95. wandb/sdk/launch/builder/docker_builder.py +7 -23
  96. wandb/sdk/launch/builder/kaniko_builder.py +12 -25
  97. wandb/sdk/launch/builder/templates/dockerfile.py +92 -0
  98. wandb/sdk/launch/create_job.py +51 -45
  99. wandb/sdk/launch/environment/aws_environment.py +26 -1
  100. wandb/sdk/launch/inputs/files.py +148 -0
  101. wandb/sdk/launch/inputs/internal.py +224 -0
  102. wandb/sdk/launch/inputs/manage.py +95 -0
  103. wandb/sdk/launch/registry/google_artifact_registry.py +1 -1
  104. wandb/sdk/launch/runner/abstract.py +2 -2
  105. wandb/sdk/launch/runner/kubernetes_monitor.py +45 -12
  106. wandb/sdk/launch/runner/kubernetes_runner.py +6 -8
  107. wandb/sdk/launch/runner/local_container.py +2 -3
  108. wandb/sdk/launch/runner/local_process.py +8 -29
  109. wandb/sdk/launch/runner/sagemaker_runner.py +20 -14
  110. wandb/sdk/launch/runner/vertex_runner.py +8 -7
  111. wandb/sdk/launch/sweeps/scheduler.py +5 -3
  112. wandb/sdk/launch/sweeps/scheduler_sweep.py +1 -1
  113. wandb/sdk/launch/sweeps/utils.py +4 -4
  114. wandb/sdk/launch/utils.py +16 -138
  115. wandb/sdk/lib/_settings_toposort_generated.py +2 -5
  116. wandb/sdk/lib/apikey.py +4 -2
  117. wandb/sdk/lib/config_util.py +3 -3
  118. wandb/sdk/lib/import_hooks.py +1 -1
  119. wandb/sdk/lib/proto_util.py +22 -1
  120. wandb/sdk/lib/redirect.py +20 -15
  121. wandb/sdk/lib/tracelog.py +1 -1
  122. wandb/sdk/service/service.py +2 -1
  123. wandb/sdk/service/streams.py +5 -5
  124. wandb/sdk/wandb_init.py +25 -59
  125. wandb/sdk/wandb_login.py +28 -25
  126. wandb/sdk/wandb_run.py +123 -53
  127. wandb/sdk/wandb_settings.py +33 -64
  128. wandb/sdk/wandb_setup.py +1 -1
  129. wandb/sdk/wandb_watch.py +1 -1
  130. wandb/sklearn/plot/classifier.py +10 -12
  131. wandb/sklearn/plot/clusterer.py +1 -1
  132. wandb/sync/sync.py +2 -2
  133. wandb/testing/relay.py +32 -17
  134. wandb/util.py +36 -37
  135. wandb/wandb_agent.py +3 -3
  136. wandb/wandb_controller.py +5 -4
  137. {wandb-0.17.0rc1.dist-info → wandb-0.17.1.dist-info}/METADATA +8 -10
  138. {wandb-0.17.0rc1.dist-info → wandb-0.17.1.dist-info}/RECORD +141 -163
  139. {wandb-0.17.0rc1.dist-info → wandb-0.17.1.dist-info}/WHEEL +1 -1
  140. wandb/apis/reports/v1/_blocks.py +0 -1406
  141. wandb/apis/reports/v1/_helpers.py +0 -70
  142. wandb/apis/reports/v1/_panels.py +0 -1282
  143. wandb/apis/reports/v1/_templates.py +0 -478
  144. wandb/apis/reports/v1/blocks.py +0 -27
  145. wandb/apis/reports/v1/helpers.py +0 -2
  146. wandb/apis/reports/v1/mutations.py +0 -66
  147. wandb/apis/reports/v1/panels.py +0 -17
  148. wandb/apis/reports/v1/report.py +0 -268
  149. wandb/apis/reports/v1/runset.py +0 -144
  150. wandb/apis/reports/v1/templates.py +0 -7
  151. wandb/apis/reports/v1/util.py +0 -406
  152. wandb/apis/reports/v1/validators.py +0 -131
  153. wandb/apis/reports/v2/blocks.py +0 -25
  154. wandb/apis/reports/v2/expr_parsing.py +0 -257
  155. wandb/apis/reports/v2/gql.py +0 -68
  156. wandb/apis/reports/v2/interface.py +0 -1911
  157. wandb/apis/reports/v2/internal.py +0 -867
  158. wandb/apis/reports/v2/metrics.py +0 -6
  159. wandb/apis/reports/v2/panels.py +0 -15
  160. wandb/catboost/__init__.py +0 -9
  161. wandb/fastai/__init__.py +0 -9
  162. wandb/keras/__init__.py +0 -19
  163. wandb/lightgbm/__init__.py +0 -9
  164. wandb/plots/__init__.py +0 -6
  165. wandb/plots/explain_text.py +0 -36
  166. wandb/plots/heatmap.py +0 -81
  167. wandb/plots/named_entity.py +0 -43
  168. wandb/plots/part_of_speech.py +0 -50
  169. wandb/plots/plot_definitions.py +0 -768
  170. wandb/plots/precision_recall.py +0 -121
  171. wandb/plots/roc.py +0 -103
  172. wandb/sacred/__init__.py +0 -3
  173. wandb/xgboost/__init__.py +0 -9
  174. {wandb-0.17.0rc1.dist-info → wandb-0.17.1.dist-info}/entry_points.txt +0 -0
  175. {wandb-0.17.0rc1.dist-info → wandb-0.17.1.dist-info}/licenses/LICENSE +0 -0
@@ -6,3 +6,5 @@ if protobuf_version == "3":
6
6
  from wandb.proto.v3.wandb_base_pb2 import *
7
7
  elif protobuf_version == "4":
8
8
  from wandb.proto.v4.wandb_base_pb2 import *
9
+ elif protobuf_version == "5":
10
+ from wandb.proto.v5.wandb_base_pb2 import *
@@ -20,7 +20,11 @@ DEPRECATED_FEATURES = Literal[
20
20
  "init__config_include_keys",
21
21
  "init__config_exclude_keys",
22
22
  "keras_callback__save_model",
23
- "langchain_tracer"
23
+ "langchain_tracer",
24
+ "artifact__get_path",
25
+ "artifactmanifestentry__name",
26
+ "api__artifact_versions",
27
+ "artifact_collection__change_type",
24
28
  ]
25
29
 
26
30
 
@@ -35,3 +39,7 @@ class Deprecated:
35
39
  init__config_exclude_keys: DEPRECATED_FEATURES = "init__config_exclude_keys"
36
40
  keras_callback__save_model: DEPRECATED_FEATURES = "keras_callback__save_model"
37
41
  langchain_tracer: DEPRECATED_FEATURES = "langchain_tracer"
42
+ artifact__get_path: DEPRECATED_FEATURES = "artifact__get_path"
43
+ artifactmanifestentry__name: DEPRECATED_FEATURES = "artifactmanifestentry__name"
44
+ api__artifact_versions: DEPRECATED_FEATURES = "api__artifact_versions"
45
+ artifact_collection__change_type: DEPRECATED_FEATURES = "artifact_collection__change_type"
@@ -0,0 +1,34 @@
1
+ #!/usr/bin/env python
2
+
3
+
4
+ def generate_deprecated_class_definition() -> None:
5
+ """Generate a class definition listing the deprecated features.
6
+ This is to allow static checks to ensure that proper field names are used.
7
+ """
8
+ from wandb.proto.wandb_telemetry_pb2 import Deprecated # type: ignore[import]
9
+
10
+ deprecated_features = Deprecated.DESCRIPTOR.fields_by_name.keys()
11
+
12
+ code: str = (
13
+ "# Generated by wandb/proto/wandb_internal_codegen.py. DO NOT EDIT!\n\n\n"
14
+ "import sys\n\n\n"
15
+ "if sys.version_info >= (3, 8):\n"
16
+ " from typing import Literal\n"
17
+ "else:\n"
18
+ " from typing_extensions import Literal\n\n\n"
19
+ "DEPRECATED_FEATURES = Literal[\n"
20
+ + ",\n".join(f' "{feature}"' for feature in deprecated_features)
21
+ + ",\n"
22
+ + "]\n\n\n"
23
+ "class Deprecated:\n"
24
+ + "".join(
25
+ [
26
+ f' {feature}: DEPRECATED_FEATURES = "{feature}"\n'
27
+ for feature in deprecated_features
28
+ ]
29
+ )
30
+ )
31
+ with open("wandb_deprecated.py", "w") as f:
32
+ f.write(code)
33
+
34
+ generate_deprecated_class_definition()
@@ -1,46 +1,14 @@
1
1
  #!/usr/bin/env python
2
2
 
3
+ import importlib.metadata
3
4
  import os
4
5
  import pathlib
5
6
 
6
7
  import grpc_tools # type: ignore
7
8
  from grpc_tools import protoc # type: ignore
8
- import importlib.metadata
9
9
  from packaging import version
10
10
 
11
11
 
12
- def generate_deprecated_class_definition() -> None:
13
- """
14
- Generate a class definition listing the deprecated features.
15
- This is to allow static checks to ensure that proper field names are used.
16
- """
17
- from wandb.proto.wandb_telemetry_pb2 import Deprecated # type: ignore[import]
18
-
19
- deprecated_features = Deprecated.DESCRIPTOR.fields_by_name.keys()
20
-
21
- code: str = (
22
- "# Generated by wandb/proto/wandb_internal_codegen.py. DO NOT EDIT!\n\n\n"
23
- "import sys\n\n\n"
24
- "if sys.version_info >= (3, 8):\n"
25
- " from typing import Literal\n"
26
- "else:\n"
27
- " from typing_extensions import Literal\n\n\n"
28
- "DEPRECATED_FEATURES = Literal[\n"
29
- + ",\n".join(f' "{feature}"' for feature in deprecated_features)
30
- + "\n"
31
- + "]\n\n\n"
32
- "class Deprecated:\n"
33
- + "".join(
34
- [
35
- f' {feature}: DEPRECATED_FEATURES = "{feature}"\n'
36
- for feature in deprecated_features
37
- ]
38
- )
39
- )
40
- with open("wandb/proto/wandb_deprecated.py", "w") as f:
41
- f.write(code)
42
-
43
-
44
12
  def get_pip_package_version(package_name: str) -> str:
45
13
  try:
46
14
  return importlib.metadata.version(package_name)
@@ -79,5 +47,3 @@ for p in (tmp_out / "wandb" / "proto").glob("*pb2*"):
79
47
  p.rename(tmp_out / p.name)
80
48
  os.rmdir(tmp_out / "wandb" / "proto")
81
49
  os.rmdir(tmp_out / "wandb")
82
-
83
- generate_deprecated_class_definition()
@@ -6,3 +6,5 @@ if protobuf_version == "3":
6
6
  from wandb.proto.v3.wandb_internal_pb2 import *
7
7
  elif protobuf_version == "4":
8
8
  from wandb.proto.v4.wandb_internal_pb2 import *
9
+ elif protobuf_version == "5":
10
+ from wandb.proto.v5.wandb_internal_pb2 import *
@@ -6,3 +6,5 @@ if protobuf_version == "3":
6
6
  from wandb.proto.v3.wandb_server_pb2 import *
7
7
  elif protobuf_version == "4":
8
8
  from wandb.proto.v4.wandb_server_pb2 import *
9
+ elif protobuf_version == "5":
10
+ from wandb.proto.v5.wandb_server_pb2 import *
@@ -6,3 +6,5 @@ if protobuf_version == "3":
6
6
  from wandb.proto.v3.wandb_settings_pb2 import *
7
7
  elif protobuf_version == "4":
8
8
  from wandb.proto.v4.wandb_settings_pb2 import *
9
+ elif protobuf_version == "5":
10
+ from wandb.proto.v5.wandb_settings_pb2 import *
@@ -6,3 +6,5 @@ if protobuf_version == "3":
6
6
  from wandb.proto.v3.wandb_telemetry_pb2 import *
7
7
  elif protobuf_version == "4":
8
8
  from wandb.proto.v4.wandb_telemetry_pb2 import *
9
+ elif protobuf_version == "5":
10
+ from wandb.proto.v5.wandb_telemetry_pb2 import *
@@ -70,6 +70,7 @@ from wandb.sdk.data_types._dtypes import TypeRegistry
70
70
  from wandb.sdk.internal.internal_api import Api as InternalApi
71
71
  from wandb.sdk.internal.thread_local_settings import _thread_local_api_settings
72
72
  from wandb.sdk.lib import filesystem, retry, runid, telemetry
73
+ from wandb.sdk.lib.deprecate import Deprecated, deprecate
73
74
  from wandb.sdk.lib.hashutil import B64MD5, b64_to_hex_id, md5_file_b64
74
75
  from wandb.sdk.lib.mailbox import Mailbox
75
76
  from wandb.sdk.lib.paths import FilePathStr, LogicalPath, StrPath, URIStr
@@ -262,11 +263,12 @@ class Artifact:
262
263
  "name": name,
263
264
  },
264
265
  )
265
- attrs = response.get("project", {}).get("artifact")
266
- if attrs is None:
267
- raise ValueError(
268
- f"Unable to fetch artifact with name {entity}/{project}/{name}"
269
- )
266
+ project_attrs = response.get("project")
267
+ if not project_attrs:
268
+ raise ValueError(f"project '{project}' not found under entity '{entity}'")
269
+ attrs = project_attrs.get("artifact")
270
+ if not attrs:
271
+ raise ValueError(f"artifact '{name}' not found in '{entity}/{project}'")
270
272
  return cls._from_attrs(entity, project, name, attrs, client)
271
273
 
272
274
  @classmethod
@@ -425,7 +427,7 @@ class Artifact:
425
427
 
426
428
  A collection is an ordered group of artifact versions.
427
429
  If this artifact was retrieved from a portfolio / linked collection, that
428
- collection will be returned rather than the the collection
430
+ collection will be returned rather than the collection
429
431
  that an artifact version originated from. The collection
430
432
  that an artifact originates from is known as the source sequence.
431
433
  """
@@ -1180,7 +1182,7 @@ class Artifact:
1180
1182
  """
1181
1183
  self._ensure_can_add()
1182
1184
  if not os.path.isfile(local_path):
1183
- raise ValueError("Path is not a file: %s" % local_path)
1185
+ raise ValueError("Path is not a file: {}".format(local_path))
1184
1186
 
1185
1187
  name = LogicalPath(name or os.path.basename(local_path))
1186
1188
  digest = md5_file_b64(local_path)
@@ -1221,11 +1223,12 @@ class Artifact:
1221
1223
  """
1222
1224
  self._ensure_can_add()
1223
1225
  if not os.path.isdir(local_path):
1224
- raise ValueError("Path is not a directory: %s" % local_path)
1226
+ raise ValueError("Path is not a directory: {}".format(local_path))
1225
1227
 
1226
1228
  termlog(
1227
- "Adding directory to artifact (%s)... "
1228
- % os.path.join(".", os.path.normpath(local_path)),
1229
+ "Adding directory to artifact ({})... ".format(
1230
+ os.path.join(".", os.path.normpath(local_path))
1231
+ ),
1229
1232
  newline=False,
1230
1233
  )
1231
1234
  start_time = time.time()
@@ -1503,8 +1506,9 @@ class Artifact:
1503
1506
 
1504
1507
  def get_path(self, name: StrPath) -> ArtifactManifestEntry:
1505
1508
  """Deprecated. Use `get_entry(name)`."""
1506
- termwarn(
1507
- "Artifact.get_path(name) is deprecated, use Artifact.get_entry(name) instead."
1509
+ deprecate(
1510
+ field_name=Deprecated.artifact__get_path,
1511
+ warning_message="Artifact.get_path(name) is deprecated, use Artifact.get_entry(name) instead.",
1508
1512
  )
1509
1513
  return self.get_entry(name)
1510
1514
 
@@ -1526,7 +1530,7 @@ class Artifact:
1526
1530
  name = LogicalPath(name)
1527
1531
  entry = self.manifest.entries.get(name) or self._get_obj_entry(name)[0]
1528
1532
  if entry is None:
1529
- raise KeyError("Path not contained in artifact: %s" % name)
1533
+ raise KeyError("Path not contained in artifact: {}".format(name))
1530
1534
  entry._parent_artifact = self
1531
1535
  return entry
1532
1536
 
@@ -1937,11 +1941,11 @@ class Artifact:
1937
1941
  for entry in self.manifest.entries.values():
1938
1942
  if entry.ref is None:
1939
1943
  if md5_file_b64(os.path.join(root, entry.path)) != entry.digest:
1940
- raise ValueError("Digest mismatch for file: %s" % entry.path)
1944
+ raise ValueError("Digest mismatch for file: {}".format(entry.path))
1941
1945
  else:
1942
1946
  ref_count += 1
1943
1947
  if ref_count > 0:
1944
- print("Warning: skipped verification of %s refs" % ref_count)
1948
+ print("Warning: skipped verification of {} refs".format(ref_count))
1945
1949
 
1946
1950
  def file(self, root: Optional[str] = None) -> StrPath:
1947
1951
  """Download a single file artifact to the directory you specify with `root`.
@@ -2057,13 +2061,13 @@ class Artifact:
2057
2061
 
2058
2062
  Arguments:
2059
2063
  target_path: The path to the portfolio inside a project.
2060
- The target path must adhere to one of the following
2061
- schemas `{portfolio}`, `{project}/{portfolio}` or
2062
- `{entity}/{project}/{portfolio}`.
2063
- To link the artifact to the Model Registry, rather than to a generic
2064
- portfolio inside a project, set `target_path` to the following
2065
- schema `{"model-registry"}/{Registered Model Name}` or
2066
- `{entity}/{"model-registry"}/{Registered Model Name}`.
2064
+ The target path must adhere to one of the following
2065
+ schemas `{portfolio}`, `{project}/{portfolio}` or
2066
+ `{entity}/{project}/{portfolio}`.
2067
+ To link the artifact to the Model Registry, rather than to a generic
2068
+ portfolio inside a project, set `target_path` to the following
2069
+ schema `{"model-registry"}/{Registered Model Name}` or
2070
+ `{entity}/{"model-registry"}/{Registered Model Name}`.
2067
2071
  aliases: A list of strings that uniquely identifies the artifact inside the
2068
2072
  specified portfolio.
2069
2073
 
@@ -2081,6 +2085,48 @@ class Artifact:
2081
2085
  else:
2082
2086
  wandb.run.link_artifact(self, target_path, aliases)
2083
2087
 
2088
+ def unlink(self) -> None:
2089
+ """Unlink this artifact if it is currently a member of a portfolio (a promoted collection of artifacts).
2090
+
2091
+ Raises:
2092
+ ArtifactNotLoggedError: If the artifact is not logged.
2093
+ ValueError: If the artifact is not linked, i.e. it is not a member of a portfolio collection.
2094
+ """
2095
+ self._ensure_logged("unlink")
2096
+
2097
+ # Fail early if this isn't a linked artifact to begin with
2098
+ if self.collection.is_sequence():
2099
+ raise ValueError(
2100
+ f"Artifact {self.qualified_name!r} is not a linked artifact and cannot be unlinked. "
2101
+ f"To delete it, use {self.delete.__qualname__!r} instead."
2102
+ )
2103
+
2104
+ self._unlink()
2105
+
2106
+ @normalize_exceptions
2107
+ def _unlink(self) -> None:
2108
+ mutation = gql(
2109
+ """
2110
+ mutation UnlinkArtifact($artifactID: ID!, $artifactPortfolioID: ID!) {
2111
+ unlinkArtifact(
2112
+ input: { artifactID: $artifactID, artifactPortfolioID: $artifactPortfolioID }
2113
+ ) {
2114
+ artifactID
2115
+ success
2116
+ clientMutationId
2117
+ }
2118
+ }
2119
+ """
2120
+ )
2121
+ assert self._client is not None
2122
+ self._client.execute(
2123
+ mutation,
2124
+ variable_values={
2125
+ "artifactID": self.id,
2126
+ "artifactPortfolioID": self.collection.id,
2127
+ },
2128
+ )
2129
+
2084
2130
  def used_by(self) -> List[Run]:
2085
2131
  """Get a list of the runs that have used this artifact.
2086
2132
 
@@ -51,7 +51,7 @@ class ArtifactManifest:
51
51
  entry.path in self.entries
52
52
  and entry.digest != self.entries[entry.path].digest
53
53
  ):
54
- raise ValueError("Cannot add the same path twice: %s" % entry.path)
54
+ raise ValueError("Cannot add the same path twice: {}".format(entry.path))
55
55
  self.entries[entry.path] = entry
56
56
 
57
57
  def remove_entry(self, entry: "ArtifactManifestEntry") -> None:
@@ -6,8 +6,8 @@ from pathlib import Path
6
6
  from typing import TYPE_CHECKING, Dict, Optional, Union
7
7
  from urllib.parse import urlparse
8
8
 
9
- from wandb.errors.term import termwarn
10
9
  from wandb.sdk.lib import filesystem
10
+ from wandb.sdk.lib.deprecate import Deprecated, deprecate
11
11
  from wandb.sdk.lib.hashutil import (
12
12
  B64MD5,
13
13
  ETag,
@@ -94,8 +94,11 @@ class ArtifactManifestEntry:
94
94
 
95
95
  @property
96
96
  def name(self) -> LogicalPath:
97
- # TODO(hugh): add telemetry to see if anyone is still using this.
98
- termwarn("ArtifactManifestEntry.name is deprecated, use .path instead")
97
+ """Deprecated; use `path` instead."""
98
+ deprecate(
99
+ field_name=Deprecated.artifactmanifestentry__name,
100
+ warning_message="ArtifactManifestEntry.name is deprecated, use .path instead.",
101
+ )
99
102
  return self.path
100
103
 
101
104
  def parent_artifact(self) -> "Artifact":
@@ -20,7 +20,7 @@ class ArtifactManifestV1(ArtifactManifest):
20
20
  ) -> "ArtifactManifestV1":
21
21
  if manifest_json["version"] != cls.version():
22
22
  raise ValueError(
23
- "Expected manifest version 1, got %s" % manifest_json["version"]
23
+ "Expected manifest version 1, got {}".format(manifest_json["version"])
24
24
  )
25
25
 
26
26
  storage_policy_name = manifest_json["storagePolicy"]
@@ -173,16 +173,7 @@ class ArtifactSaver:
173
173
  self._file_pusher.store_manifest_files(
174
174
  self._manifest,
175
175
  artifact_id,
176
- lambda entry,
177
- progress_callback: self._manifest.storage_policy.store_file_sync(
178
- artifact_id,
179
- artifact_manifest_id,
180
- entry,
181
- step_prepare,
182
- progress_callback=progress_callback,
183
- ),
184
- lambda entry,
185
- progress_callback: self._manifest.storage_policy.store_file_async(
176
+ lambda entry, progress_callback: self._manifest.storage_policy.store_file(
186
177
  artifact_id,
187
178
  artifact_manifest_id,
188
179
  entry,
@@ -43,7 +43,9 @@ class LocalFileHandler(StorageHandler):
43
43
  local_path = util.local_file_uri_to_path(str(manifest_entry.ref))
44
44
  if not os.path.exists(local_path):
45
45
  raise ValueError(
46
- "Local file reference: Failed to find file at path %s" % local_path
46
+ "Local file reference: Failed to find file at path {}".format(
47
+ local_path
48
+ )
47
49
  )
48
50
 
49
51
  path, hit, cache_open = self._cache.check_md5_obj_path(
@@ -131,5 +133,7 @@ class LocalFileHandler(StorageHandler):
131
133
  entries.append(entry)
132
134
  else:
133
135
  # TODO: update error message if we don't allow directories.
134
- raise ValueError('Path "%s" must be a valid file or directory path' % path)
136
+ raise ValueError(
137
+ 'Path "{}" must be a valid file or directory path'.format(path)
138
+ )
135
139
  return entries
@@ -29,7 +29,7 @@ class MultiHandler(StorageHandler):
29
29
  return handler
30
30
  if self._default_handler is not None:
31
31
  return self._default_handler
32
- raise ValueError('No storage handler registered for url "%s"' % str(url))
32
+ raise ValueError('No storage handler registered for url "{}"'.format(str(url)))
33
33
 
34
34
  def load_path(
35
35
  self,
@@ -57,12 +57,14 @@ class TrackingHandler(StorageHandler):
57
57
  url = urlparse(path)
58
58
  if name is None:
59
59
  raise ValueError(
60
- 'You must pass name="<entry_name>" when tracking references with unknown schemes. ref: %s'
61
- % path
60
+ 'You must pass name="<entry_name>" when tracking references with unknown schemes. ref: {}'.format(
61
+ path
62
+ )
62
63
  )
63
64
  termwarn(
64
- "Artifact references with unsupported schemes cannot be checksummed: %s"
65
- % path
65
+ "Artifact references with unsupported schemes cannot be checksummed: {}".format(
66
+ path
67
+ )
66
68
  )
67
69
  name = name or url.path[1:] # strip leading slash
68
70
  return [ArtifactManifestEntry(path=name, ref=path, digest=path)]
@@ -263,7 +263,7 @@ class WandbStoragePolicy(StoragePolicy):
263
263
  return math.ceil(file_size / S3_MAX_PART_NUMBERS)
264
264
  return default_chunk_size
265
265
 
266
- def store_file_sync(
266
+ def store_file(
267
267
  self,
268
268
  artifact_id: str,
269
269
  artifact_manifest_id: str,
@@ -301,7 +301,7 @@ class WandbStoragePolicy(StoragePolicy):
301
301
  hex_digests[part_number] = hex_digest
302
302
  part_number += 1
303
303
 
304
- resp = preparer.prepare_sync(
304
+ resp = preparer.prepare(
305
305
  {
306
306
  "artifactID": artifact_id,
307
307
  "artifactManifestID": artifact_manifest_id,
@@ -347,46 +347,6 @@ class WandbStoragePolicy(StoragePolicy):
347
347
 
348
348
  return False
349
349
 
350
- async def store_file_async(
351
- self,
352
- artifact_id: str,
353
- artifact_manifest_id: str,
354
- entry: "ArtifactManifestEntry",
355
- preparer: "StepPrepare",
356
- progress_callback: Optional["progress.ProgressFn"] = None,
357
- ) -> bool:
358
- """Async equivalent to `store_file_sync`."""
359
- resp = await preparer.prepare_async(
360
- {
361
- "artifactID": artifact_id,
362
- "artifactManifestID": artifact_manifest_id,
363
- "name": entry.path,
364
- "md5": entry.digest,
365
- }
366
- )
367
-
368
- entry.birth_artifact_id = resp.birth_artifact_id
369
- if resp.upload_url is None:
370
- return True
371
- if entry.local_path is None:
372
- return False
373
-
374
- with open(entry.local_path, "rb") as file:
375
- # This fails if we don't send the first byte before the signed URL expires.
376
- await self._api.upload_file_retry_async(
377
- resp.upload_url,
378
- file,
379
- progress_callback,
380
- extra_headers={
381
- header.split(":", 1)[0]: header.split(":", 1)[1]
382
- for header in (resp.upload_headers or {})
383
- },
384
- )
385
-
386
- self._write_cache(entry)
387
-
388
- return False
389
-
390
350
  def _write_cache(self, entry: "ArtifactManifestEntry") -> None:
391
351
  if entry.local_path is None:
392
352
  return
@@ -43,7 +43,7 @@ class StoragePolicy:
43
43
  ) -> FilePathStr:
44
44
  raise NotImplementedError
45
45
 
46
- def store_file_sync(
46
+ def store_file(
47
47
  self,
48
48
  artifact_id: str,
49
49
  artifact_manifest_id: str,
@@ -53,17 +53,6 @@ class StoragePolicy:
53
53
  ) -> bool:
54
54
  raise NotImplementedError
55
55
 
56
- async def store_file_async(
57
- self,
58
- artifact_id: str,
59
- artifact_manifest_id: str,
60
- entry: "ArtifactManifestEntry",
61
- preparer: "StepPrepare",
62
- progress_callback: Optional["ProgressFn"] = None,
63
- ) -> bool:
64
- """Async equivalent to `store_file_sync`."""
65
- raise NotImplementedError
66
-
67
56
  def store_reference(
68
57
  self,
69
58
  artifact: "Artifact",
@@ -14,7 +14,7 @@ np = get_module("numpy") # intentionally not required
14
14
  if t.TYPE_CHECKING:
15
15
  from wandb.sdk.artifacts.artifact import Artifact
16
16
 
17
- ConvertableToType = t.Union["Type", t.Type["Type"], type, t.Any]
17
+ ConvertibleToType = t.Union["Type", t.Type["Type"], type, t.Any]
18
18
 
19
19
 
20
20
  class TypeRegistry:
@@ -84,7 +84,7 @@ class TypeRegistry:
84
84
  return _type.from_json(json_dict, artifact)
85
85
 
86
86
  @staticmethod
87
- def type_from_dtype(dtype: ConvertableToType) -> "Type":
87
+ def type_from_dtype(dtype: ConvertibleToType) -> "Type":
88
88
  # The dtype is already an instance of Type
89
89
  if isinstance(dtype, Type):
90
90
  wbtype: Type = dtype
@@ -528,7 +528,7 @@ class UnionType(Type):
528
528
 
529
529
  def __init__(
530
530
  self,
531
- allowed_types: t.Optional[t.Sequence[ConvertableToType]] = None,
531
+ allowed_types: t.Optional[t.Sequence[ConvertibleToType]] = None,
532
532
  ):
533
533
  assert allowed_types is None or (allowed_types.__class__ == list)
534
534
  if allowed_types is None:
@@ -576,7 +576,7 @@ class UnionType(Type):
576
576
  return "{}".format(" or ".join([str(t) for t in self.params["allowed_types"]]))
577
577
 
578
578
 
579
- def OptionalType(dtype: ConvertableToType) -> UnionType: # noqa: N802
579
+ def OptionalType(dtype: ConvertibleToType) -> UnionType: # noqa: N802
580
580
  """Function that mimics the Type class API for constructing an "Optional Type".
581
581
 
582
582
  This is just a Union[wb_type, NoneType].
@@ -591,14 +591,14 @@ def OptionalType(dtype: ConvertableToType) -> UnionType: # noqa: N802
591
591
 
592
592
 
593
593
  class ListType(Type):
594
- """A list of homogenous types."""
594
+ """A list of homogeneous types."""
595
595
 
596
596
  name = "list"
597
597
  types: t.ClassVar[t.List[type]] = [list, tuple, set, frozenset]
598
598
 
599
599
  def __init__(
600
600
  self,
601
- element_type: t.Optional[ConvertableToType] = None,
601
+ element_type: t.Optional[ConvertibleToType] = None,
602
602
  length: t.Optional[int] = None,
603
603
  ):
604
604
  if element_type is None:
@@ -691,7 +691,7 @@ class ListType(Type):
691
691
 
692
692
 
693
693
  class NDArrayType(Type):
694
- """Represents a list of homogenous types."""
694
+ """Represents a list of homogeneous types."""
695
695
 
696
696
  name = "ndarray"
697
697
  types: t.ClassVar[t.List[type]] = [] # will manually add type if np is available
@@ -786,7 +786,7 @@ class TypedDictType(Type):
786
786
 
787
787
  def __init__(
788
788
  self,
789
- type_map: t.Optional[t.Dict[str, ConvertableToType]] = None,
789
+ type_map: t.Optional[t.Dict[str, ConvertibleToType]] = None,
790
790
  ):
791
791
  if type_map is None:
792
792
  type_map = {}
@@ -167,7 +167,7 @@ class Image(BatchableMedia):
167
167
  self._file_type = None
168
168
 
169
169
  # Allows the user to pass an Image object as the first parameter and have a perfect copy,
170
- # only overriding additional metdata passed in. If this pattern is compelling, we can generalize.
170
+ # only overriding additional metadata passed in. If this pattern is compelling, we can generalize.
171
171
  if isinstance(data_or_path, Image):
172
172
  self._initialize_from_wbimage(data_or_path)
173
173
  elif isinstance(data_or_path, str):
@@ -480,7 +480,7 @@ class Image(BatchableMedia):
480
480
  return "RGBA"
481
481
  else:
482
482
  raise ValueError(
483
- "Un-supported shape for image conversion %s" % list(data.shape)
483
+ "Un-supported shape for image conversion {}".format(list(data.shape))
484
484
  )
485
485
 
486
486
  @classmethod
@@ -24,7 +24,7 @@ if TYPE_CHECKING: # pragma: no cover
24
24
  # https://github.com/wandb/wandb/issues/3472
25
25
  #
26
26
  # Essentially, the issue is that moviepy's write_gif function fails to close
27
- # the open write / file descripter returned from `imageio.save`. The following
27
+ # the open write / file descriptor returned from `imageio.save`. The following
28
28
  # function is a simplified copy of the function in the moviepy source code.
29
29
  # See https://github.com/Zulko/moviepy/blob/7e3e8bb1b739eb6d1c0784b0cb2594b587b93b39/moviepy/video/io/gif_writers.py#L428
30
30
  #
@@ -96,7 +96,9 @@ class Video(BatchableMedia):
96
96
  self._channels = None
97
97
  self._caption = caption
98
98
  if self._format not in Video.EXTS:
99
- raise ValueError("wandb.Video accepts %s formats" % ", ".join(Video.EXTS))
99
+ raise ValueError(
100
+ "wandb.Video accepts {} formats".format(", ".join(Video.EXTS))
101
+ )
100
102
 
101
103
  if isinstance(data_or_path, BytesIO):
102
104
  filename = os.path.join(
@@ -110,7 +112,7 @@ class Video(BatchableMedia):
110
112
  ext = ext[1:].lower()
111
113
  if ext not in Video.EXTS:
112
114
  raise ValueError(
113
- "wandb.Video accepts %s formats" % ", ".join(Video.EXTS)
115
+ "wandb.Video accepts {} formats".format(", ".join(Video.EXTS))
114
116
  )
115
117
  self._set_file(data_or_path, is_tmp=False)
116
118
  # ffprobe -v error -select_streams v:0 -show_entries stream=width,height -of csv=p=0 data_or_path