wandb 0.21.1__py3-none-win32.whl → 0.21.2__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.
- wandb/__init__.py +1 -1
- wandb/__init__.pyi +1 -1
- wandb/apis/public/api.py +1 -2
- wandb/apis/public/artifacts.py +3 -5
- wandb/apis/public/registries/_utils.py +14 -16
- wandb/apis/public/registries/registries_search.py +176 -289
- wandb/apis/public/reports.py +13 -10
- wandb/automations/_generated/delete_automation.py +1 -3
- wandb/automations/_generated/enums.py +13 -11
- wandb/bin/gpu_stats.exe +0 -0
- wandb/bin/wandb-core +0 -0
- wandb/cli/cli.py +47 -2
- wandb/integration/metaflow/data_pandas.py +2 -2
- wandb/integration/metaflow/data_pytorch.py +75 -0
- wandb/integration/metaflow/data_sklearn.py +76 -0
- wandb/integration/metaflow/metaflow.py +16 -87
- wandb/integration/weave/__init__.py +6 -0
- wandb/integration/weave/interface.py +49 -0
- wandb/integration/weave/weave.py +63 -0
- wandb/proto/v3/wandb_internal_pb2.py +3 -2
- wandb/proto/v4/wandb_internal_pb2.py +2 -2
- wandb/proto/v5/wandb_internal_pb2.py +2 -2
- wandb/proto/v6/wandb_internal_pb2.py +2 -2
- wandb/sdk/artifacts/_factories.py +17 -0
- wandb/sdk/artifacts/_generated/__init__.py +221 -13
- wandb/sdk/artifacts/_generated/artifact_by_id.py +17 -0
- wandb/sdk/artifacts/_generated/artifact_by_name.py +22 -0
- wandb/sdk/artifacts/_generated/artifact_collection_membership_file_urls.py +43 -0
- wandb/sdk/artifacts/_generated/artifact_created_by.py +47 -0
- wandb/sdk/artifacts/_generated/artifact_file_urls.py +22 -0
- wandb/sdk/artifacts/_generated/artifact_type.py +31 -0
- wandb/sdk/artifacts/_generated/artifact_used_by.py +43 -0
- wandb/sdk/artifacts/_generated/artifact_via_membership_by_name.py +26 -0
- wandb/sdk/artifacts/_generated/delete_artifact.py +28 -0
- wandb/sdk/artifacts/_generated/enums.py +5 -0
- wandb/sdk/artifacts/_generated/fetch_artifact_manifest.py +38 -0
- wandb/sdk/artifacts/_generated/fetch_registries.py +32 -0
- wandb/sdk/artifacts/_generated/fragments.py +279 -41
- wandb/sdk/artifacts/_generated/link_artifact.py +6 -0
- wandb/sdk/artifacts/_generated/operations.py +654 -51
- wandb/sdk/artifacts/_generated/registry_collections.py +34 -0
- wandb/sdk/artifacts/_generated/registry_versions.py +34 -0
- wandb/sdk/artifacts/_generated/unlink_artifact.py +25 -0
- wandb/sdk/artifacts/_graphql_fragments.py +3 -86
- wandb/sdk/artifacts/_validators.py +6 -4
- wandb/sdk/artifacts/artifact.py +406 -543
- wandb/sdk/artifacts/artifact_file_cache.py +10 -6
- wandb/sdk/artifacts/artifact_manifest.py +10 -9
- wandb/sdk/artifacts/artifact_manifest_entry.py +9 -10
- wandb/sdk/artifacts/artifact_manifests/artifact_manifest_v1.py +5 -3
- wandb/sdk/artifacts/storage_handlers/http_handler.py +1 -1
- wandb/sdk/artifacts/storage_handlers/s3_handler.py +1 -1
- wandb/sdk/artifacts/storage_policies/wandb_storage_policy.py +1 -1
- wandb/sdk/data_types/video.py +2 -2
- wandb/sdk/interface/interface_queue.py +1 -4
- wandb/sdk/interface/interface_shared.py +26 -37
- wandb/sdk/interface/interface_sock.py +24 -14
- wandb/sdk/internal/settings_static.py +2 -3
- wandb/sdk/launch/create_job.py +12 -1
- wandb/sdk/launch/runner/kubernetes_runner.py +24 -29
- wandb/sdk/lib/asyncio_compat.py +16 -16
- wandb/sdk/lib/asyncio_manager.py +252 -0
- wandb/sdk/lib/hashutil.py +13 -4
- wandb/sdk/lib/printer.py +2 -2
- wandb/sdk/lib/printer_asyncio.py +3 -1
- wandb/sdk/lib/retry.py +185 -78
- wandb/sdk/lib/service/service_client.py +106 -0
- wandb/sdk/lib/service/service_connection.py +20 -26
- wandb/sdk/lib/service/service_token.py +30 -13
- wandb/sdk/mailbox/mailbox.py +13 -5
- wandb/sdk/mailbox/mailbox_handle.py +22 -13
- wandb/sdk/mailbox/response_handle.py +42 -106
- wandb/sdk/mailbox/wait_with_progress.py +7 -42
- wandb/sdk/wandb_init.py +11 -25
- wandb/sdk/wandb_login.py +1 -1
- wandb/sdk/wandb_run.py +91 -55
- wandb/sdk/wandb_settings.py +45 -32
- wandb/sdk/wandb_setup.py +176 -96
- wandb/util.py +1 -1
- {wandb-0.21.1.dist-info → wandb-0.21.2.dist-info}/METADATA +1 -1
- {wandb-0.21.1.dist-info → wandb-0.21.2.dist-info}/RECORD +84 -68
- wandb/sdk/interface/interface_relay.py +0 -38
- wandb/sdk/interface/router.py +0 -89
- wandb/sdk/interface/router_queue.py +0 -43
- wandb/sdk/interface/router_relay.py +0 -50
- wandb/sdk/interface/router_sock.py +0 -32
- wandb/sdk/lib/sock_client.py +0 -232
- {wandb-0.21.1.dist-info → wandb-0.21.2.dist-info}/WHEEL +0 -0
- {wandb-0.21.1.dist-info → wandb-0.21.2.dist-info}/entry_points.txt +0 -0
- {wandb-0.21.1.dist-info → wandb-0.21.2.dist-info}/licenses/LICENSE +0 -0
@@ -1,57 +1,53 @@
|
|
1
1
|
"""Public API: registries search."""
|
2
2
|
|
3
|
-
import
|
4
|
-
from typing import TYPE_CHECKING, Any, Dict, Optional
|
3
|
+
from __future__ import annotations
|
5
4
|
|
6
|
-
|
7
|
-
|
5
|
+
import json
|
6
|
+
from typing import TYPE_CHECKING, Any
|
8
7
|
|
8
|
+
from pydantic import ValidationError
|
9
|
+
from typing_extensions import override
|
9
10
|
from wandb_gql import gql
|
10
11
|
|
11
|
-
import wandb
|
12
12
|
from wandb.apis.paginator import Paginator
|
13
|
-
from wandb.
|
14
|
-
|
15
|
-
|
13
|
+
from wandb.apis.public.utils import gql_compat
|
14
|
+
from wandb.sdk.artifacts._generated import (
|
15
|
+
FETCH_REGISTRIES_GQL,
|
16
|
+
REGISTRY_COLLECTIONS_GQL,
|
17
|
+
REGISTRY_VERSIONS_GQL,
|
18
|
+
ArtifactCollectionType,
|
19
|
+
FetchRegistries,
|
20
|
+
RegistriesPage,
|
21
|
+
RegistryCollections,
|
22
|
+
RegistryCollectionsPage,
|
23
|
+
RegistryVersions,
|
24
|
+
RegistryVersionsPage,
|
16
25
|
)
|
26
|
+
from wandb.sdk.artifacts._graphql_fragments import omit_artifact_fields
|
17
27
|
from wandb.sdk.artifacts._validators import remove_registry_prefix
|
18
28
|
|
19
29
|
from ._utils import ensure_registry_prefix_on_names
|
20
30
|
|
31
|
+
if TYPE_CHECKING:
|
32
|
+
from wandb_gql import Client
|
33
|
+
|
34
|
+
from wandb.sdk.artifacts.artifact import Artifact
|
35
|
+
|
21
36
|
|
22
37
|
class Registries(Paginator):
|
23
38
|
"""An lazy iterator of `Registry` objects."""
|
24
39
|
|
25
|
-
QUERY = gql(
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
orgEntity {
|
30
|
-
name
|
31
|
-
projects(filters: $filters, after: $cursor, first: $perPage) {
|
32
|
-
pageInfo {
|
33
|
-
endCursor
|
34
|
-
hasNextPage
|
35
|
-
}
|
36
|
-
edges {
|
37
|
-
node {
|
38
|
-
...RegistryFragment
|
39
|
-
}
|
40
|
-
}
|
41
|
-
}
|
42
|
-
}
|
43
|
-
}
|
44
|
-
}
|
45
|
-
"""
|
46
|
-
+ _gql_registry_fragment()
|
47
|
-
)
|
40
|
+
QUERY = gql(FETCH_REGISTRIES_GQL)
|
41
|
+
|
42
|
+
last_response: RegistriesPage | None
|
43
|
+
_last_org_entity: str | None
|
48
44
|
|
49
45
|
def __init__(
|
50
46
|
self,
|
51
|
-
client:
|
47
|
+
client: Client,
|
52
48
|
organization: str,
|
53
|
-
filter:
|
54
|
-
per_page:
|
49
|
+
filter: dict[str, Any] | None = None,
|
50
|
+
per_page: int | None = 100,
|
55
51
|
):
|
56
52
|
self.client = client
|
57
53
|
self.organization = organization
|
@@ -63,6 +59,8 @@ class Registries(Paginator):
|
|
63
59
|
|
64
60
|
super().__init__(client, variables, per_page)
|
65
61
|
|
62
|
+
self._last_org_entity = None
|
63
|
+
|
66
64
|
def __next__(self):
|
67
65
|
# Implement custom next since its possible to load empty pages because of auth
|
68
66
|
self.index += 1
|
@@ -71,18 +69,18 @@ class Registries(Paginator):
|
|
71
69
|
raise StopIteration
|
72
70
|
return self.objects[self.index]
|
73
71
|
|
74
|
-
def collections(self, filter:
|
72
|
+
def collections(self, filter: dict[str, Any] | None = None) -> Collections:
|
75
73
|
return Collections(
|
76
|
-
self.client,
|
77
|
-
self.organization,
|
74
|
+
client=self.client,
|
75
|
+
organization=self.organization,
|
78
76
|
registry_filter=self.filter,
|
79
77
|
collection_filter=filter,
|
80
78
|
)
|
81
79
|
|
82
|
-
def versions(self, filter:
|
80
|
+
def versions(self, filter: dict[str, Any] | None = None) -> Versions:
|
83
81
|
return Versions(
|
84
|
-
self.client,
|
85
|
-
self.organization,
|
82
|
+
client=self.client,
|
83
|
+
organization=self.organization,
|
86
84
|
registry_filter=self.filter,
|
87
85
|
collection_filter=None,
|
88
86
|
artifact_filter=filter,
|
@@ -90,132 +88,71 @@ class Registries(Paginator):
|
|
90
88
|
|
91
89
|
@property
|
92
90
|
def length(self):
|
93
|
-
if self.last_response:
|
94
|
-
return len(
|
95
|
-
self.last_response["organization"]["orgEntity"]["projects"]["edges"]
|
96
|
-
)
|
97
|
-
else:
|
91
|
+
if self.last_response is None:
|
98
92
|
return None
|
93
|
+
return len(self.last_response.edges)
|
99
94
|
|
100
95
|
@property
|
101
96
|
def more(self):
|
102
|
-
if self.last_response:
|
103
|
-
return self.last_response["organization"]["orgEntity"]["projects"][
|
104
|
-
"pageInfo"
|
105
|
-
]["hasNextPage"]
|
106
|
-
else:
|
97
|
+
if self.last_response is None:
|
107
98
|
return True
|
99
|
+
return self.last_response.page_info.has_next_page
|
108
100
|
|
109
101
|
@property
|
110
102
|
def cursor(self):
|
111
|
-
if self.last_response:
|
112
|
-
return self.last_response["organization"]["orgEntity"]["projects"][
|
113
|
-
"pageInfo"
|
114
|
-
]["endCursor"]
|
115
|
-
else:
|
103
|
+
if self.last_response is None:
|
116
104
|
return None
|
105
|
+
return self.last_response.page_info.end_cursor
|
117
106
|
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
or not self.last_response["organization"]["orgEntity"]
|
124
|
-
):
|
107
|
+
@override
|
108
|
+
def _update_response(self) -> None:
|
109
|
+
data = self.client.execute(self.QUERY, variable_values=self.variables)
|
110
|
+
result = FetchRegistries.model_validate(data)
|
111
|
+
if not ((org := result.organization) and (org_entity := org.org_entity)):
|
125
112
|
raise ValueError(
|
126
|
-
f"Organization
|
113
|
+
f"Organization {self.organization!r} not found. Please verify the organization name is correct."
|
127
114
|
)
|
128
115
|
|
116
|
+
try:
|
117
|
+
page_data = org_entity.projects
|
118
|
+
self.last_response = RegistriesPage.model_validate(page_data)
|
119
|
+
self._last_org_entity = org_entity.name
|
120
|
+
except (LookupError, AttributeError, ValidationError) as e:
|
121
|
+
raise ValueError("Unexpected response data") from e
|
122
|
+
|
123
|
+
def convert_objects(self):
|
129
124
|
from wandb.apis.public.registries.registry import Registry
|
130
125
|
|
126
|
+
if (self.last_response is None) or (self._last_org_entity is None):
|
127
|
+
return []
|
128
|
+
|
129
|
+
nodes = (e.node for e in self.last_response.edges)
|
131
130
|
return [
|
132
131
|
Registry(
|
133
|
-
self.client,
|
134
|
-
self.organization,
|
135
|
-
self.
|
136
|
-
remove_registry_prefix(
|
137
|
-
|
132
|
+
client=self.client,
|
133
|
+
organization=self.organization,
|
134
|
+
entity=self._last_org_entity,
|
135
|
+
name=remove_registry_prefix(node.name),
|
136
|
+
attrs=node.model_dump(),
|
138
137
|
)
|
139
|
-
for
|
140
|
-
"edges"
|
141
|
-
]
|
138
|
+
for node in nodes
|
142
139
|
]
|
143
140
|
|
144
141
|
|
145
142
|
class Collections(Paginator["ArtifactCollection"]):
|
146
143
|
"""An lazy iterator of `ArtifactCollection` objects in a Registry."""
|
147
144
|
|
148
|
-
QUERY = gql(
|
149
|
-
|
150
|
-
|
151
|
-
$organization: String!,
|
152
|
-
$registryFilter: JSONString,
|
153
|
-
$collectionFilter: JSONString,
|
154
|
-
$collectionTypes: [ArtifactCollectionType!],
|
155
|
-
$cursor: String,
|
156
|
-
$perPage: Int
|
157
|
-
) {
|
158
|
-
organization(name: $organization) {
|
159
|
-
orgEntity {
|
160
|
-
name
|
161
|
-
artifactCollections(
|
162
|
-
projectFilters: $registryFilter,
|
163
|
-
filters: $collectionFilter,
|
164
|
-
collectionTypes: $collectionTypes,
|
165
|
-
after: $cursor,
|
166
|
-
first: $perPage
|
167
|
-
) {
|
168
|
-
totalCount
|
169
|
-
pageInfo {
|
170
|
-
endCursor
|
171
|
-
hasNextPage
|
172
|
-
}
|
173
|
-
edges {
|
174
|
-
cursor
|
175
|
-
node {
|
176
|
-
id
|
177
|
-
name
|
178
|
-
description
|
179
|
-
createdAt
|
180
|
-
tags {
|
181
|
-
edges {
|
182
|
-
node {
|
183
|
-
name
|
184
|
-
}
|
185
|
-
}
|
186
|
-
}
|
187
|
-
project {
|
188
|
-
name
|
189
|
-
entity {
|
190
|
-
name
|
191
|
-
}
|
192
|
-
}
|
193
|
-
defaultArtifactType {
|
194
|
-
name
|
195
|
-
}
|
196
|
-
aliases {
|
197
|
-
edges {
|
198
|
-
node {
|
199
|
-
alias
|
200
|
-
}
|
201
|
-
}
|
202
|
-
}
|
203
|
-
}
|
204
|
-
}
|
205
|
-
}
|
206
|
-
}
|
207
|
-
}
|
208
|
-
}
|
209
|
-
"""
|
210
|
-
)
|
145
|
+
QUERY = gql(REGISTRY_COLLECTIONS_GQL)
|
146
|
+
|
147
|
+
last_response: RegistryCollectionsPage | None
|
211
148
|
|
212
149
|
def __init__(
|
213
150
|
self,
|
214
|
-
client:
|
151
|
+
client: Client,
|
215
152
|
organization: str,
|
216
|
-
registry_filter:
|
217
|
-
collection_filter:
|
218
|
-
per_page:
|
153
|
+
registry_filter: dict[str, Any] | None = None,
|
154
|
+
collection_filter: dict[str, Any] | None = None,
|
155
|
+
per_page: int | None = 100,
|
219
156
|
):
|
220
157
|
self.client = client
|
221
158
|
self.organization = organization
|
@@ -223,14 +160,10 @@ class Collections(Paginator["ArtifactCollection"]):
|
|
223
160
|
self.collection_filter = collection_filter or {}
|
224
161
|
|
225
162
|
variables = {
|
226
|
-
"registryFilter": (
|
227
|
-
|
228
|
-
|
229
|
-
"
|
230
|
-
json.dumps(self.collection_filter) if self.collection_filter else None
|
231
|
-
),
|
232
|
-
"organization": self.organization,
|
233
|
-
"collectionTypes": ["PORTFOLIO"],
|
163
|
+
"registryFilter": json.dumps(f) if (f := registry_filter) else None,
|
164
|
+
"collectionFilter": json.dumps(f) if (f := collection_filter) else None,
|
165
|
+
"organization": organization,
|
166
|
+
"collectionTypes": [ArtifactCollectionType.PORTFOLIO],
|
234
167
|
"perPage": per_page,
|
235
168
|
}
|
236
169
|
|
@@ -244,10 +177,10 @@ class Collections(Paginator["ArtifactCollection"]):
|
|
244
177
|
raise StopIteration
|
245
178
|
return self.objects[self.index]
|
246
179
|
|
247
|
-
def versions(self, filter:
|
180
|
+
def versions(self, filter: dict[str, Any] | None = None) -> Versions:
|
248
181
|
return Versions(
|
249
|
-
self.client,
|
250
|
-
self.organization,
|
182
|
+
client=self.client,
|
183
|
+
organization=self.organization,
|
251
184
|
registry_filter=self.registry_filter,
|
252
185
|
collection_filter=self.collection_filter,
|
253
186
|
artifact_filter=filter,
|
@@ -255,71 +188,75 @@ class Collections(Paginator["ArtifactCollection"]):
|
|
255
188
|
|
256
189
|
@property
|
257
190
|
def length(self):
|
258
|
-
if self.last_response:
|
259
|
-
return self.last_response["organization"]["orgEntity"][
|
260
|
-
"artifactCollections"
|
261
|
-
]["totalCount"]
|
262
|
-
else:
|
191
|
+
if self.last_response is None:
|
263
192
|
return None
|
193
|
+
return self.last_response.total_count
|
264
194
|
|
265
195
|
@property
|
266
196
|
def more(self):
|
267
|
-
if self.last_response:
|
268
|
-
return self.last_response["organization"]["orgEntity"][
|
269
|
-
"artifactCollections"
|
270
|
-
]["pageInfo"]["hasNextPage"]
|
271
|
-
else:
|
197
|
+
if self.last_response is None:
|
272
198
|
return True
|
199
|
+
return self.last_response.page_info.has_next_page
|
273
200
|
|
274
201
|
@property
|
275
202
|
def cursor(self):
|
276
|
-
if self.last_response:
|
277
|
-
return self.last_response["organization"]["orgEntity"][
|
278
|
-
"artifactCollections"
|
279
|
-
]["pageInfo"]["endCursor"]
|
280
|
-
else:
|
203
|
+
if self.last_response is None:
|
281
204
|
return None
|
205
|
+
return self.last_response.page_info.end_cursor
|
206
|
+
|
207
|
+
@override
|
208
|
+
def _update_response(self) -> None:
|
209
|
+
data = self.client.execute(self.QUERY, variable_values=self.variables)
|
210
|
+
result = RegistryCollections.model_validate(data)
|
211
|
+
if not (
|
212
|
+
(org_data := result.organization)
|
213
|
+
and (org_entity_data := org_data.org_entity)
|
214
|
+
):
|
215
|
+
raise ValueError(
|
216
|
+
f"Organization {self.organization!r} not found. Please verify the organization name is correct."
|
217
|
+
)
|
218
|
+
|
219
|
+
try:
|
220
|
+
page_data = org_entity_data.artifact_collections
|
221
|
+
self.last_response = RegistryCollectionsPage.model_validate(page_data)
|
222
|
+
except (LookupError, AttributeError, ValidationError) as e:
|
223
|
+
raise ValueError("Unexpected response data") from e
|
282
224
|
|
283
225
|
def convert_objects(self):
|
284
226
|
from wandb.apis.public import ArtifactCollection
|
285
227
|
|
286
|
-
if
|
228
|
+
if self.last_response is None:
|
287
229
|
return []
|
288
|
-
if (
|
289
|
-
not self.last_response["organization"]
|
290
|
-
or not self.last_response["organization"]["orgEntity"]
|
291
|
-
):
|
292
|
-
raise ValueError(
|
293
|
-
f"Organization '{self.organization}' not found. Please verify the organization name is correct"
|
294
|
-
)
|
295
230
|
|
231
|
+
nodes = (e.node for e in self.last_response.edges)
|
296
232
|
return [
|
297
233
|
ArtifactCollection(
|
298
|
-
self.client,
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
self.organization,
|
304
|
-
|
234
|
+
client=self.client,
|
235
|
+
entity=project.entity.name,
|
236
|
+
project=project.name,
|
237
|
+
name=node.name,
|
238
|
+
type=node.default_artifact_type.name,
|
239
|
+
organization=self.organization,
|
240
|
+
attrs=node.model_dump(),
|
305
241
|
is_sequence=False,
|
306
242
|
)
|
307
|
-
for
|
308
|
-
|
309
|
-
]["edges"]
|
243
|
+
for node in nodes
|
244
|
+
if (project := node.project)
|
310
245
|
]
|
311
246
|
|
312
247
|
|
313
248
|
class Versions(Paginator["Artifact"]):
|
314
249
|
"""An lazy iterator of `Artifact` objects in a Registry."""
|
315
250
|
|
251
|
+
last_response: RegistryVersionsPage | None
|
252
|
+
|
316
253
|
def __init__(
|
317
254
|
self,
|
318
|
-
client:
|
255
|
+
client: Client,
|
319
256
|
organization: str,
|
320
|
-
registry_filter:
|
321
|
-
collection_filter:
|
322
|
-
artifact_filter:
|
257
|
+
registry_filter: dict[str, Any] | None = None,
|
258
|
+
collection_filter: dict[str, Any] | None = None,
|
259
|
+
artifact_filter: dict[str, Any] | None = None,
|
323
260
|
per_page: int = 100,
|
324
261
|
):
|
325
262
|
self.client = client
|
@@ -327,69 +264,16 @@ class Versions(Paginator["Artifact"]):
|
|
327
264
|
self.registry_filter = registry_filter
|
328
265
|
self.collection_filter = collection_filter
|
329
266
|
self.artifact_filter = artifact_filter or {}
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
$organization: String!,
|
334
|
-
$registryFilter: JSONString,
|
335
|
-
$collectionFilter: JSONString,
|
336
|
-
$artifactFilter: JSONString,
|
337
|
-
$cursor: String,
|
338
|
-
$perPage: Int
|
339
|
-
) {
|
340
|
-
organization(name: $organization) {
|
341
|
-
orgEntity {
|
342
|
-
name
|
343
|
-
artifactMemberships(
|
344
|
-
projectFilters: $registryFilter,
|
345
|
-
collectionFilters: $collectionFilter,
|
346
|
-
filters: $artifactFilter,
|
347
|
-
after: $cursor,
|
348
|
-
first: $perPage
|
349
|
-
) {
|
350
|
-
pageInfo {
|
351
|
-
endCursor
|
352
|
-
hasNextPage
|
353
|
-
}
|
354
|
-
edges {
|
355
|
-
node {
|
356
|
-
artifactCollection {
|
357
|
-
project {
|
358
|
-
name
|
359
|
-
entity {
|
360
|
-
name
|
361
|
-
}
|
362
|
-
}
|
363
|
-
name
|
364
|
-
}
|
365
|
-
versionIndex
|
366
|
-
artifact {
|
367
|
-
...ArtifactFragment
|
368
|
-
}
|
369
|
-
aliases {
|
370
|
-
alias
|
371
|
-
}
|
372
|
-
}
|
373
|
-
}
|
374
|
-
}
|
375
|
-
}
|
376
|
-
}
|
377
|
-
}
|
378
|
-
"""
|
379
|
-
+ _gql_artifact_fragment(include_aliases=False)
|
267
|
+
|
268
|
+
self.QUERY = gql_compat(
|
269
|
+
REGISTRY_VERSIONS_GQL, omit_fields=omit_artifact_fields()
|
380
270
|
)
|
381
271
|
|
382
272
|
variables = {
|
383
|
-
"registryFilter": (
|
384
|
-
|
385
|
-
),
|
386
|
-
"
|
387
|
-
json.dumps(self.collection_filter) if self.collection_filter else None
|
388
|
-
),
|
389
|
-
"artifactFilter": (
|
390
|
-
json.dumps(self.artifact_filter) if self.artifact_filter else None
|
391
|
-
),
|
392
|
-
"organization": self.organization,
|
273
|
+
"registryFilter": json.dumps(f) if (f := registry_filter) else None,
|
274
|
+
"collectionFilter": json.dumps(f) if (f := collection_filter) else None,
|
275
|
+
"artifactFilter": json.dumps(f) if (f := artifact_filter) else None,
|
276
|
+
"organization": organization,
|
393
277
|
}
|
394
278
|
|
395
279
|
super().__init__(client, variables, per_page)
|
@@ -403,58 +287,61 @@ class Versions(Paginator["Artifact"]):
|
|
403
287
|
return self.objects[self.index]
|
404
288
|
|
405
289
|
@property
|
406
|
-
def length(self):
|
407
|
-
if self.last_response:
|
408
|
-
return len(
|
409
|
-
self.last_response["organization"]["orgEntity"]["artifactMemberships"][
|
410
|
-
"edges"
|
411
|
-
]
|
412
|
-
)
|
413
|
-
else:
|
290
|
+
def length(self) -> int | None:
|
291
|
+
if self.last_response is None:
|
414
292
|
return None
|
293
|
+
return len(self.last_response.edges)
|
415
294
|
|
416
295
|
@property
|
417
|
-
def more(self):
|
418
|
-
if self.last_response:
|
419
|
-
return self.last_response["organization"]["orgEntity"][
|
420
|
-
"artifactMemberships"
|
421
|
-
]["pageInfo"]["hasNextPage"]
|
422
|
-
else:
|
296
|
+
def more(self) -> bool:
|
297
|
+
if self.last_response is None:
|
423
298
|
return True
|
299
|
+
return self.last_response.page_info.has_next_page
|
424
300
|
|
425
301
|
@property
|
426
|
-
def cursor(self):
|
427
|
-
if self.last_response:
|
428
|
-
return self.last_response["organization"]["orgEntity"][
|
429
|
-
"artifactMemberships"
|
430
|
-
]["pageInfo"]["endCursor"]
|
431
|
-
else:
|
302
|
+
def cursor(self) -> str | None:
|
303
|
+
if self.last_response is None:
|
432
304
|
return None
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
305
|
+
return self.last_response.page_info.end_cursor
|
306
|
+
|
307
|
+
@override
|
308
|
+
def _update_response(self) -> None:
|
309
|
+
data = self.client.execute(self.QUERY, variable_values=self.variables)
|
310
|
+
result = RegistryVersions.model_validate(data)
|
311
|
+
if not (
|
312
|
+
(org_data := result.organization)
|
313
|
+
and (org_entity_data := org_data.org_entity)
|
440
314
|
):
|
441
315
|
raise ValueError(
|
442
|
-
f"Organization
|
316
|
+
f"Organization {self.organization!r} not found. Please verify the organization name is correct."
|
443
317
|
)
|
444
318
|
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
319
|
+
try:
|
320
|
+
page_data = org_entity_data.artifact_memberships
|
321
|
+
self.last_response = RegistryVersionsPage.model_validate(page_data)
|
322
|
+
except (LookupError, AttributeError, ValidationError) as e:
|
323
|
+
raise ValueError("Unexpected response data") from e
|
324
|
+
|
325
|
+
def convert_objects(self) -> list[Artifact]:
|
326
|
+
from wandb.sdk.artifacts.artifact import Artifact
|
327
|
+
|
328
|
+
if self.last_response is None:
|
329
|
+
return []
|
330
|
+
|
331
|
+
nodes = (e.node for e in self.last_response.edges)
|
332
|
+
return [
|
333
|
+
Artifact._from_attrs(
|
334
|
+
entity=project.entity.name,
|
335
|
+
project=project.name,
|
336
|
+
name=f"{collection.name}:v{node.version_index}",
|
337
|
+
attrs=artifact,
|
338
|
+
client=self.client,
|
339
|
+
aliases=[alias.alias for alias in node.aliases],
|
455
340
|
)
|
456
|
-
for
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
341
|
+
for node in nodes
|
342
|
+
if (
|
343
|
+
(collection := node.artifact_collection)
|
344
|
+
and (project := collection.project)
|
345
|
+
and (artifact := node.artifact)
|
346
|
+
)
|
347
|
+
]
|
wandb/apis/public/reports.py
CHANGED
@@ -141,18 +141,21 @@ class Reports(SizedPaginator["BetaReport"]):
|
|
141
141
|
class BetaReport(Attrs):
|
142
142
|
"""BetaReport is a class associated with reports created in W&B.
|
143
143
|
|
144
|
-
|
144
|
+
Provides access to report attributes (name, description, user, spec,
|
145
|
+
timestamps) and methods for retrieving associated runs,
|
146
|
+
sections, and for rendering the report as HTML.
|
145
147
|
|
146
148
|
Attributes:
|
147
|
-
id (string):
|
148
|
-
|
149
|
-
|
150
|
-
description (string): report
|
151
|
-
user (User):
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
149
|
+
id (string): Unique identifier of the report.
|
150
|
+
display_name (string): Human-readable display name of the report.
|
151
|
+
name (string): The name of the report. Use `display_name` for a more user-friendly name.
|
152
|
+
description (string): Description of the report.
|
153
|
+
user (User): Dictionary containing user info (username, email) who
|
154
|
+
created the report.
|
155
|
+
spec (dict): The spec of the report.
|
156
|
+
url (string): The URL of the report.
|
157
|
+
updated_at (string): Timestamp of last update.
|
158
|
+
created_at (string): Timestamp when the report was created.
|
156
159
|
"""
|
157
160
|
|
158
161
|
def __init__(self, client, attrs, entity=None, project=None):
|
@@ -3,15 +3,13 @@
|
|
3
3
|
|
4
4
|
from __future__ import annotations
|
5
5
|
|
6
|
-
from typing import Optional
|
7
|
-
|
8
6
|
from wandb._pydantic import GQLBase
|
9
7
|
|
10
8
|
from .fragments import DeleteAutomationResult
|
11
9
|
|
12
10
|
|
13
11
|
class DeleteAutomation(GQLBase):
|
14
|
-
result:
|
12
|
+
result: DeleteAutomationResult
|
15
13
|
|
16
14
|
|
17
15
|
DeleteAutomation.model_rebuild()
|