wandb 0.21.4__py3-none-win32.whl → 0.22.1__py3-none-win32.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (96) hide show
  1. wandb/__init__.py +1 -1
  2. wandb/__init__.pyi +3 -3
  3. wandb/_pydantic/__init__.py +12 -11
  4. wandb/_pydantic/base.py +49 -19
  5. wandb/apis/__init__.py +2 -0
  6. wandb/apis/attrs.py +2 -0
  7. wandb/apis/importers/internals/internal.py +16 -23
  8. wandb/apis/internal.py +2 -0
  9. wandb/apis/normalize.py +2 -0
  10. wandb/apis/public/__init__.py +44 -1
  11. wandb/apis/public/api.py +215 -164
  12. wandb/apis/public/artifacts.py +23 -20
  13. wandb/apis/public/const.py +2 -0
  14. wandb/apis/public/files.py +33 -24
  15. wandb/apis/public/history.py +2 -0
  16. wandb/apis/public/jobs.py +20 -18
  17. wandb/apis/public/projects.py +4 -2
  18. wandb/apis/public/query_generator.py +3 -0
  19. wandb/apis/public/registries/__init__.py +7 -0
  20. wandb/apis/public/registries/_freezable_list.py +9 -12
  21. wandb/apis/public/registries/registries_search.py +8 -6
  22. wandb/apis/public/registries/registry.py +22 -17
  23. wandb/apis/public/reports.py +2 -0
  24. wandb/apis/public/runs.py +282 -60
  25. wandb/apis/public/sweeps.py +10 -9
  26. wandb/apis/public/teams.py +2 -0
  27. wandb/apis/public/users.py +2 -0
  28. wandb/apis/public/utils.py +16 -15
  29. wandb/automations/_generated/__init__.py +54 -127
  30. wandb/automations/_generated/create_generic_webhook_integration.py +1 -7
  31. wandb/automations/_generated/fragments.py +26 -91
  32. wandb/bin/gpu_stats.exe +0 -0
  33. wandb/bin/wandb-core +0 -0
  34. wandb/cli/beta_sync.py +9 -11
  35. wandb/errors/errors.py +3 -3
  36. wandb/proto/v3/wandb_internal_pb2.py +234 -224
  37. wandb/proto/v3/wandb_sync_pb2.py +19 -6
  38. wandb/proto/v4/wandb_internal_pb2.py +226 -224
  39. wandb/proto/v4/wandb_sync_pb2.py +10 -6
  40. wandb/proto/v5/wandb_internal_pb2.py +226 -224
  41. wandb/proto/v5/wandb_sync_pb2.py +10 -6
  42. wandb/proto/v6/wandb_base_pb2.py +3 -3
  43. wandb/proto/v6/wandb_internal_pb2.py +229 -227
  44. wandb/proto/v6/wandb_server_pb2.py +3 -3
  45. wandb/proto/v6/wandb_settings_pb2.py +3 -3
  46. wandb/proto/v6/wandb_sync_pb2.py +13 -9
  47. wandb/proto/v6/wandb_telemetry_pb2.py +3 -3
  48. wandb/sdk/artifacts/_factories.py +7 -2
  49. wandb/sdk/artifacts/_generated/__init__.py +112 -412
  50. wandb/sdk/artifacts/_generated/fragments.py +65 -0
  51. wandb/sdk/artifacts/_generated/operations.py +52 -22
  52. wandb/sdk/artifacts/_generated/run_input_artifacts.py +3 -23
  53. wandb/sdk/artifacts/_generated/run_output_artifacts.py +3 -23
  54. wandb/sdk/artifacts/_generated/type_info.py +19 -0
  55. wandb/sdk/artifacts/_gqlutils.py +47 -0
  56. wandb/sdk/artifacts/_models/__init__.py +4 -0
  57. wandb/sdk/artifacts/_models/base_model.py +20 -0
  58. wandb/sdk/artifacts/_validators.py +40 -12
  59. wandb/sdk/artifacts/artifact.py +69 -88
  60. wandb/sdk/artifacts/artifact_file_cache.py +6 -1
  61. wandb/sdk/artifacts/artifact_manifest_entry.py +61 -2
  62. wandb/sdk/artifacts/storage_handlers/gcs_handler.py +1 -1
  63. wandb/sdk/artifacts/storage_handlers/http_handler.py +1 -3
  64. wandb/sdk/artifacts/storage_handlers/local_file_handler.py +1 -1
  65. wandb/sdk/artifacts/storage_handlers/s3_handler.py +1 -1
  66. wandb/sdk/artifacts/storage_policies/_factories.py +63 -0
  67. wandb/sdk/artifacts/storage_policies/wandb_storage_policy.py +69 -124
  68. wandb/sdk/data_types/bokeh.py +5 -1
  69. wandb/sdk/data_types/image.py +17 -6
  70. wandb/sdk/interface/interface.py +41 -4
  71. wandb/sdk/interface/interface_queue.py +10 -0
  72. wandb/sdk/interface/interface_shared.py +9 -7
  73. wandb/sdk/interface/interface_sock.py +9 -3
  74. wandb/sdk/internal/_generated/__init__.py +2 -12
  75. wandb/sdk/internal/sender.py +1 -1
  76. wandb/sdk/internal/settings_static.py +2 -82
  77. wandb/sdk/launch/runner/kubernetes_runner.py +25 -20
  78. wandb/sdk/launch/utils.py +82 -1
  79. wandb/sdk/lib/progress.py +7 -4
  80. wandb/sdk/lib/service/service_client.py +5 -9
  81. wandb/sdk/lib/service/service_connection.py +39 -23
  82. wandb/sdk/mailbox/mailbox_handle.py +2 -0
  83. wandb/sdk/projects/_generated/__init__.py +12 -33
  84. wandb/sdk/wandb_init.py +31 -3
  85. wandb/sdk/wandb_login.py +53 -27
  86. wandb/sdk/wandb_run.py +5 -3
  87. wandb/sdk/wandb_settings.py +50 -13
  88. wandb/sync/sync.py +7 -2
  89. wandb/util.py +1 -1
  90. wandb/wandb_agent.py +35 -4
  91. {wandb-0.21.4.dist-info → wandb-0.22.1.dist-info}/METADATA +1 -1
  92. {wandb-0.21.4.dist-info → wandb-0.22.1.dist-info}/RECORD +95 -91
  93. wandb/sdk/artifacts/_graphql_fragments.py +0 -19
  94. {wandb-0.21.4.dist-info → wandb-0.22.1.dist-info}/WHEEL +0 -0
  95. {wandb-0.21.4.dist-info → wandb-0.22.1.dist-info}/entry_points.txt +0 -0
  96. {wandb-0.21.4.dist-info → wandb-0.22.1.dist-info}/licenses/LICENSE +0 -0
@@ -51,12 +51,13 @@ from wandb.sdk.artifacts._generated import (
51
51
  ProjectArtifacts,
52
52
  ProjectArtifactType,
53
53
  ProjectArtifactTypes,
54
- RunInputArtifactsProjectRunInputArtifacts,
55
- RunOutputArtifactsProjectRunOutputArtifacts,
54
+ RunInputArtifactConnectionFragment,
55
+ RunOutputArtifactConnectionFragment,
56
56
  )
57
- from wandb.sdk.artifacts._graphql_fragments import omit_artifact_fields
57
+ from wandb.sdk.artifacts._gqlutils import omit_artifact_fields
58
58
  from wandb.sdk.artifacts._validators import (
59
59
  SOURCE_ARTIFACT_COLLECTION_TYPE,
60
+ FullArtifactPath,
60
61
  validate_artifact_name,
61
62
  validate_artifact_type,
62
63
  )
@@ -715,7 +716,7 @@ class Artifacts(SizedPaginator["Artifact"]):
715
716
 
716
717
  self.QUERY = gql_compat(
717
718
  PROJECT_ARTIFACTS_GQL,
718
- omit_fields=omit_artifact_fields(),
719
+ omit_fields=omit_artifact_fields(client),
719
720
  rename_fields=rename_fields,
720
721
  )
721
722
 
@@ -778,10 +779,12 @@ class Artifacts(SizedPaginator["Artifact"]):
778
779
  artifact_edges = (edge for edge in self.last_response.edges if edge.node)
779
780
  artifacts = (
780
781
  wandb.Artifact._from_attrs(
781
- entity=self.entity,
782
- project=self.project,
783
- name=f"{self.collection_name}:{edge.version}",
784
- attrs=edge.node.model_dump(exclude_unset=True),
782
+ path=FullArtifactPath(
783
+ prefix=self.entity,
784
+ project=self.project,
785
+ name=f"{self.collection_name}:{edge.version}",
786
+ ),
787
+ attrs=edge.node,
785
788
  client=self.client,
786
789
  )
787
790
  for edge in artifact_edges
@@ -797,14 +800,12 @@ class RunArtifacts(SizedPaginator["Artifact"]):
797
800
  """
798
801
 
799
802
  last_response: (
800
- RunOutputArtifactsProjectRunOutputArtifacts
801
- | RunInputArtifactsProjectRunInputArtifacts
803
+ RunOutputArtifactConnectionFragment | RunInputArtifactConnectionFragment
802
804
  )
803
805
 
804
806
  #: The pydantic model used to parse the (inner part of the) raw response.
805
807
  _response_cls: type[
806
- RunOutputArtifactsProjectRunOutputArtifacts
807
- | RunInputArtifactsProjectRunInputArtifacts
808
+ RunOutputArtifactConnectionFragment | RunInputArtifactConnectionFragment
808
809
  ]
809
810
 
810
811
  def __init__(
@@ -819,15 +820,15 @@ class RunArtifacts(SizedPaginator["Artifact"]):
819
820
  if mode == "logged":
820
821
  self.run_key = "outputArtifacts"
821
822
  self.QUERY = gql_compat(
822
- RUN_OUTPUT_ARTIFACTS_GQL, omit_fields=omit_artifact_fields()
823
+ RUN_OUTPUT_ARTIFACTS_GQL, omit_fields=omit_artifact_fields(client)
823
824
  )
824
- self._response_cls = RunOutputArtifactsProjectRunOutputArtifacts
825
+ self._response_cls = RunOutputArtifactConnectionFragment
825
826
  elif mode == "used":
826
827
  self.run_key = "inputArtifacts"
827
828
  self.QUERY = gql_compat(
828
- RUN_INPUT_ARTIFACTS_GQL, omit_fields=omit_artifact_fields()
829
+ RUN_INPUT_ARTIFACTS_GQL, omit_fields=omit_artifact_fields(client)
829
830
  )
830
- self._response_cls = RunInputArtifactsProjectRunInputArtifacts
831
+ self._response_cls = RunInputArtifactConnectionFragment
831
832
  else:
832
833
  raise ValueError("mode must be logged or used")
833
834
 
@@ -886,10 +887,12 @@ class RunArtifacts(SizedPaginator["Artifact"]):
886
887
 
887
888
  return [
888
889
  wandb.Artifact._from_attrs(
889
- entity=proj.entity_name,
890
- project=proj.name,
891
- name=f"{artifact_seq.name}:v{node.version_index}",
892
- attrs=node.model_dump(exclude_unset=True),
890
+ path=FullArtifactPath(
891
+ prefix=proj.entity_name,
892
+ project=proj.name,
893
+ name=f"{artifact_seq.name}:v{node.version_index}",
894
+ ),
895
+ attrs=node,
893
896
  client=self.client,
894
897
  )
895
898
  for edge in self.last_response.edges
@@ -1,3 +1,5 @@
1
+ from __future__ import annotations
2
+
1
3
  import datetime
2
4
 
3
5
  # Only retry requests for 20 seconds in the public api
@@ -49,7 +49,7 @@ from wandb.apis.paginator import SizedPaginator
49
49
  from wandb.apis.public import utils
50
50
  from wandb.apis.public.api import Api, RetryingClient
51
51
  from wandb.apis.public.const import RETRY_TIMEDELTA
52
- from wandb.apis.public.runs import Run
52
+ from wandb.apis.public.runs import Run, _server_provides_internal_id_for_project
53
53
  from wandb.sdk.lib import retry
54
54
 
55
55
  FILE_FRAGMENT = """fragment RunFilesFragment on Run {
@@ -103,21 +103,24 @@ class Files(SizedPaginator["File"]):
103
103
  ```
104
104
  """
105
105
 
106
- QUERY = gql(
107
- """
108
- query RunFiles($project: String!, $entity: String!, $name: String!, $fileCursor: String,
109
- $fileLimit: Int = 50, $fileNames: [String] = [], $upload: Boolean = false, $pattern: String) {{
110
- project(name: $project, entityName: $entity) {{
111
- internalId
112
- run(name: $name) {{
113
- fileCount
114
- ...RunFilesFragment
106
+ def _get_query(self):
107
+ """Generate query dynamically based on server capabilities."""
108
+ with_internal_id = _server_provides_internal_id_for_project(self.client)
109
+ return gql(
110
+ f"""
111
+ query RunFiles($project: String!, $entity: String!, $name: String!, $fileCursor: String,
112
+ $fileLimit: Int = 50, $fileNames: [String] = [], $upload: Boolean = false, $pattern: String) {{
113
+ project(name: $project, entityName: $entity) {{
114
+ {"internalId" if with_internal_id else ""}
115
+ run(name: $name) {{
116
+ fileCount
117
+ ...RunFilesFragment
118
+ }}
115
119
  }}
116
120
  }}
117
- }}
118
- {}
119
- """.format(FILE_FRAGMENT)
120
- )
121
+ {FILE_FRAGMENT}
122
+ """
123
+ )
121
124
 
122
125
  def __init__(
123
126
  self,
@@ -133,15 +136,15 @@ class Files(SizedPaginator["File"]):
133
136
  Files are retrieved in pages from the W&B server as needed.
134
137
 
135
138
  Args:
136
- client: The run object that contains the files
137
- run: The run object that contains the files
138
- names (list, optional): A list of file names to filter the files
139
- per_page (int, optional): The number of files to fetch per page
140
- upload (bool, optional): If `True`, fetch the upload URL for each file
141
- pattern (str, optional): Pattern to match when returning files from W&B
142
- This pattern uses mySQL's LIKE syntax,
143
- so matching all files that end with .json would be "%.json".
144
- If both names and pattern are provided, a ValueError will be raised.
139
+ client: The run object that contains the files
140
+ run: The run object that contains the files
141
+ names (list, optional): A list of file names to filter the files
142
+ per_page (int, optional): The number of files to fetch per page
143
+ upload (bool, optional): If `True`, fetch the upload URL for each file
144
+ pattern (str, optional): Pattern to match when returning files from W&B
145
+ This pattern uses mySQL's LIKE syntax,
146
+ so matching all files that end with .json would be "%.json".
147
+ If both names and pattern are provided, a ValueError will be raised.
145
148
  """
146
149
  if names and pattern:
147
150
  raise ValueError(
@@ -160,6 +163,12 @@ class Files(SizedPaginator["File"]):
160
163
  }
161
164
  super().__init__(client, variables, per_page)
162
165
 
166
+ def _update_response(self) -> None:
167
+ """Fetch and store the response data for the next page using dynamic query."""
168
+ self.last_response = self.client.execute(
169
+ self._get_query(), variable_values=self.variables
170
+ )
171
+
163
172
  @property
164
173
  def _length(self):
165
174
  """
@@ -244,7 +253,7 @@ class File(Attrs):
244
253
  attrs (dict): A dictionary of attributes that define the file
245
254
  run: The run object that contains the file
246
255
 
247
- <!-- lazydoc-ignore-class: internal -->
256
+ <!-- lazydoc-ignore-init: internal -->
248
257
  """
249
258
 
250
259
  def __init__(self, client, attrs, run=None):
@@ -9,6 +9,8 @@ Note:
9
9
  both complete and sampled access to metrics logged during training runs.
10
10
  """
11
11
 
12
+ from __future__ import annotations
13
+
12
14
  import json
13
15
 
14
16
  from wandb_gql import gql
wandb/apis/public/jobs.py CHANGED
@@ -4,11 +4,13 @@ This module provides classes for managing W&B jobs, queued runs, and run
4
4
  queues.
5
5
  """
6
6
 
7
+ from __future__ import annotations
8
+
7
9
  import json
8
10
  import os
9
11
  import shutil
10
12
  import time
11
- from typing import TYPE_CHECKING, Any, Dict, List, Literal, Mapping, Optional
13
+ from typing import TYPE_CHECKING, Any, Literal, Mapping
12
14
 
13
15
  from wandb_gql import gql
14
16
 
@@ -37,11 +39,11 @@ class Job:
37
39
  _output_types: Type
38
40
  _entity: str
39
41
  _project: str
40
- _entrypoint: List[str]
42
+ _entrypoint: list[str]
41
43
  _notebook_job: bool
42
44
  _partial: bool
43
45
 
44
- def __init__(self, api: "Api", name, path: Optional[str] = None) -> None:
46
+ def __init__(self, api: Api, name, path: str | None = None) -> None:
45
47
  try:
46
48
  self._job_artifact = api._artifact(name, type="job")
47
49
  except CommError:
@@ -166,7 +168,7 @@ class Job:
166
168
  if self._entrypoint:
167
169
  launch_project.set_job_entry_point(self._entrypoint)
168
170
 
169
- def set_entrypoint(self, entrypoint: List[str]):
171
+ def set_entrypoint(self, entrypoint: list[str]):
170
172
  """Set the entrypoint for the job."""
171
173
  self._entrypoint = entrypoint
172
174
 
@@ -307,7 +309,7 @@ class QueuedRun:
307
309
  )
308
310
 
309
311
  @normalize_exceptions
310
- def _get_run_queue_item_legacy(self) -> Dict:
312
+ def _get_run_queue_item_legacy(self) -> dict:
311
313
  query = gql(
312
314
  """
313
315
  query GetRunQueueItem($projectName: String!, $entityName: String!, $runQueue: String!) {
@@ -490,13 +492,13 @@ class RunQueue:
490
492
 
491
493
  def __init__(
492
494
  self,
493
- client: "RetryingClient",
495
+ client: RetryingClient,
494
496
  name: str,
495
497
  entity: str,
496
- prioritization_mode: Optional[RunQueuePrioritizationMode] = None,
497
- _access: Optional[RunQueueAccessType] = None,
498
- _default_resource_config_id: Optional[int] = None,
499
- _default_resource_config: Optional[dict] = None,
498
+ prioritization_mode: RunQueuePrioritizationMode | None = None,
499
+ _access: RunQueueAccessType | None = None,
500
+ _default_resource_config_id: int | None = None,
501
+ _default_resource_config: dict | None = None,
500
502
  ) -> None:
501
503
  self._name: str = name
502
504
  self._client = client
@@ -538,7 +540,7 @@ class RunQueue:
538
540
  return self._access
539
541
 
540
542
  @property
541
- def external_links(self) -> Dict[str, str]:
543
+ def external_links(self) -> dict[str, str]:
542
544
  """External resource links for the queue."""
543
545
  if self._external_links is None:
544
546
  self._get_metadata()
@@ -579,7 +581,7 @@ class RunQueue:
579
581
  return self._id
580
582
 
581
583
  @property
582
- def items(self) -> List[QueuedRun]:
584
+ def items(self) -> list[QueuedRun]:
583
585
  """Up to the first 100 queued runs. Modifying this list will not modify the queue or any enqueued items!"""
584
586
  # TODO(np): Add a paginated interface
585
587
  if self._items is None:
@@ -716,12 +718,12 @@ class RunQueue:
716
718
  def create(
717
719
  cls,
718
720
  name: str,
719
- resource: "RunQueueResourceType",
720
- entity: Optional[str] = None,
721
- prioritization_mode: Optional["RunQueuePrioritizationMode"] = None,
722
- config: Optional[dict] = None,
723
- template_variables: Optional[dict] = None,
724
- ) -> "RunQueue":
721
+ resource: RunQueueResourceType,
722
+ entity: str | None = None,
723
+ prioritization_mode: RunQueuePrioritizationMode | None = None,
724
+ config: dict | None = None,
725
+ template_variables: dict | None = None,
726
+ ) -> RunQueue:
725
727
  """Create a RunQueue.
726
728
 
727
729
  Args:
@@ -31,6 +31,8 @@ Note:
31
31
  with a new project name.
32
32
  """
33
33
 
34
+ from __future__ import annotations
35
+
34
36
  from requests import HTTPError
35
37
  from wandb_gql import gql
36
38
 
@@ -100,7 +102,7 @@ class Projects(Paginator["Project"]):
100
102
  client: RetryingClient,
101
103
  entity: str,
102
104
  per_page: int = 50,
103
- ) -> "Projects":
105
+ ) -> Projects:
104
106
  """An iterable collection of `Project` objects.
105
107
 
106
108
  Args:
@@ -187,7 +189,7 @@ class Project(Attrs):
187
189
  entity: str,
188
190
  project: str,
189
191
  attrs: dict,
190
- ) -> "Project":
192
+ ) -> Project:
191
193
  """A single project associated with an entity.
192
194
 
193
195
  Args:
@@ -1,3 +1,6 @@
1
+ from __future__ import annotations
2
+
3
+
1
4
  class QueryGenerator:
2
5
  """QueryGenerator is a helper object to write filters for runs.
3
6
 
@@ -0,0 +1,7 @@
1
+ __all__ = [
2
+ "Registry", # doc:exclude
3
+ "Registries", # doc:exclude
4
+ ]
5
+
6
+ from .registries_search import Registries
7
+ from .registry import Registry
@@ -1,14 +1,13 @@
1
+ from __future__ import annotations
2
+
1
3
  from itertools import chain
2
4
  from typing import (
3
5
  Any,
4
6
  Iterable,
5
7
  Iterator,
6
- List,
7
8
  MutableSequence,
8
9
  Sequence,
9
- Tuple,
10
10
  TypeVar,
11
- Union,
12
11
  final,
13
12
  overload,
14
13
  )
@@ -29,9 +28,9 @@ class FreezableList(MutableSequence[T]):
29
28
  Any initial items passed to the constructor are saved.
30
29
  """
31
30
 
32
- def __init__(self, iterable: Union[Iterable[T], None] = None, /) -> None:
33
- self._frozen: Tuple[T, ...] = tuple(iterable or ())
34
- self._draft: List[T] = []
31
+ def __init__(self, iterable: Iterable[T] | None = None, /) -> None:
32
+ self._frozen: tuple[T, ...] = tuple(iterable or ())
33
+ self._draft: list[T] = []
35
34
 
36
35
  def append(self, value: T) -> None:
37
36
  """Append an item to the draft list. No duplicates are allowed."""
@@ -72,7 +71,7 @@ class FreezableList(MutableSequence[T]):
72
71
  @overload
73
72
  def __getitem__(self, index: slice) -> Sequence[T]: ...
74
73
 
75
- def __getitem__(self, index: Union[int, slice]) -> Union[T, Sequence[T]]:
74
+ def __getitem__(self, index: int | slice) -> T | Sequence[T]:
76
75
  return [*self._frozen, *self._draft][index]
77
76
 
78
77
  @overload
@@ -81,9 +80,7 @@ class FreezableList(MutableSequence[T]):
81
80
  @overload
82
81
  def __setitem__(self, index: slice, value: Iterable[T]) -> None: ...
83
82
 
84
- def __setitem__(
85
- self, index: Union[int, slice], value: Union[T, Iterable[T]]
86
- ) -> None:
83
+ def __setitem__(self, index: int | slice, value: T | Iterable[T]) -> None:
87
84
  if isinstance(index, slice):
88
85
  # Setting slices might affect saved items, disallow for simplicity
89
86
  raise TypeError(f"{nameof(type(self))!r} does not support slice assignment")
@@ -109,7 +106,7 @@ class FreezableList(MutableSequence[T]):
109
106
  @overload
110
107
  def __delitem__(self, index: slice) -> None: ...
111
108
 
112
- def __delitem__(self, index: Union[int, slice]) -> None:
109
+ def __delitem__(self, index: int | slice) -> None:
113
110
  if isinstance(index, slice):
114
111
  raise TypeError(f"{nameof(type(self))!r} does not support slice deletion")
115
112
  else:
@@ -161,7 +158,7 @@ class FreezableList(MutableSequence[T]):
161
158
  return f"{nameof(type(self))}(frozen={list(self._frozen)!r}, draft={list(self._draft)!r})"
162
159
 
163
160
  @property
164
- def draft(self) -> Tuple[T, ...]:
161
+ def draft(self) -> tuple[T, ...]:
165
162
  """A read-only, tuple copy of the current draft items."""
166
163
  return tuple(self._draft)
167
164
 
@@ -24,8 +24,8 @@ from wandb.sdk.artifacts._generated import (
24
24
  RegistryVersions,
25
25
  RegistryVersionsPage,
26
26
  )
27
- from wandb.sdk.artifacts._graphql_fragments import omit_artifact_fields
28
- from wandb.sdk.artifacts._validators import remove_registry_prefix
27
+ from wandb.sdk.artifacts._gqlutils import omit_artifact_fields
28
+ from wandb.sdk.artifacts._validators import FullArtifactPath, remove_registry_prefix
29
29
 
30
30
  from ._utils import ensure_registry_prefix_on_names
31
31
 
@@ -270,7 +270,7 @@ class Versions(Paginator["Artifact"]):
270
270
  self.artifact_filter = artifact_filter or {}
271
271
 
272
272
  self.QUERY = gql_compat(
273
- REGISTRY_VERSIONS_GQL, omit_fields=omit_artifact_fields()
273
+ REGISTRY_VERSIONS_GQL, omit_fields=omit_artifact_fields(client)
274
274
  )
275
275
 
276
276
  variables = {
@@ -335,9 +335,11 @@ class Versions(Paginator["Artifact"]):
335
335
  nodes = (e.node for e in self.last_response.edges)
336
336
  return [
337
337
  Artifact._from_attrs(
338
- entity=project.entity.name,
339
- project=project.name,
340
- name=f"{collection.name}:v{node.version_index}",
338
+ path=FullArtifactPath(
339
+ prefix=project.entity.name,
340
+ project=project.name,
341
+ name=f"{collection.name}:v{node.version_index}",
342
+ ),
341
343
  attrs=artifact,
342
344
  client=self.client,
343
345
  aliases=[alias.alias for alias in node.aliases],
@@ -1,4 +1,6 @@
1
- from typing import TYPE_CHECKING, Any, Dict, List, Literal, Optional
1
+ from __future__ import annotations
2
+
3
+ from typing import TYPE_CHECKING, Any, Literal
2
4
 
3
5
  from wandb_gql import gql
4
6
 
@@ -35,11 +37,11 @@ class Registry:
35
37
 
36
38
  def __init__(
37
39
  self,
38
- client: "Client",
40
+ client: Client,
39
41
  organization: str,
40
42
  entity: str,
41
43
  name: str,
42
- attrs: Optional[Dict[str, Any]] = None,
44
+ attrs: dict[str, Any] | None = None,
43
45
  ):
44
46
  self.client = client
45
47
  self._name = name
@@ -49,7 +51,7 @@ class Registry:
49
51
  if attrs is not None:
50
52
  self._update_attributes(attrs)
51
53
 
52
- def _update_attributes(self, attrs: Dict[str, Any]) -> None:
54
+ def _update_attributes(self, attrs: dict[str, Any]) -> None:
53
55
  """Helper method to update instance attributes from a dictionary."""
54
56
  self._id = attrs.get("id", "")
55
57
  if self._id is None:
@@ -127,14 +129,17 @@ class Registry:
127
129
  Previously saved artifact types cannot be removed.
128
130
 
129
131
  Example:
130
- ```python
131
- registry.artifact_types.append("model")
132
- registry.save() # once saved, the artifact type `model` cannot be removed
133
- registry.artifact_types.append("accidentally_added")
134
- registry.artifact_types.remove(
135
- "accidentally_added"
136
- ) # Types can only be removed if it has not been saved yet
137
- ```
132
+ ```python
133
+ import wandb
134
+
135
+ registry = wandb.Api().create_registry()
136
+ registry.artifact_types.append("model")
137
+ registry.save() # once saved, the artifact type `model` cannot be removed
138
+ registry.artifact_types.append("accidentally_added")
139
+ registry.artifact_types.remove(
140
+ "accidentally_added"
141
+ ) # Types can only be removed if it has not been saved yet
142
+ ```
138
143
  """
139
144
  return self._artifact_types
140
145
 
@@ -179,7 +184,7 @@ class Registry:
179
184
  self._visibility = value
180
185
 
181
186
  @tracked
182
- def collections(self, filter: Optional[Dict[str, Any]] = None) -> Collections:
187
+ def collections(self, filter: dict[str, Any] | None = None) -> Collections:
183
188
  """Returns the collections belonging to the registry."""
184
189
  registry_filter = {
185
190
  "name": self.full_name,
@@ -187,7 +192,7 @@ class Registry:
187
192
  return Collections(self.client, self.organization, registry_filter, filter)
188
193
 
189
194
  @tracked
190
- def versions(self, filter: Optional[Dict[str, Any]] = None) -> Versions:
195
+ def versions(self, filter: dict[str, Any] | None = None) -> Versions:
191
196
  """Returns the versions belonging to the registry."""
192
197
  registry_filter = {
193
198
  "name": self.full_name,
@@ -198,12 +203,12 @@ class Registry:
198
203
  @tracked
199
204
  def create(
200
205
  cls,
201
- client: "Client",
206
+ client: Client,
202
207
  organization: str,
203
208
  name: str,
204
209
  visibility: Literal["organization", "restricted"],
205
- description: Optional[str] = None,
206
- artifact_types: Optional[List[str]] = None,
210
+ description: str | None = None,
211
+ artifact_types: list[str] | None = None,
207
212
  ):
208
213
  """Create a new registry.
209
214
 
@@ -4,6 +4,8 @@ This module provides classes for interacting with W&B reports and
4
4
  managing report-related data.
5
5
  """
6
6
 
7
+ from __future__ import annotations
8
+
7
9
  import ast
8
10
  import json
9
11
  import re