wandb 0.22.2__py3-none-win_amd64.whl → 0.22.3__py3-none-win_amd64.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 +2 -2
- wandb/_pydantic/__init__.py +8 -1
- wandb/_pydantic/base.py +54 -18
- wandb/_pydantic/field_types.py +8 -3
- wandb/_pydantic/pagination.py +46 -0
- wandb/_pydantic/utils.py +2 -2
- wandb/apis/public/api.py +24 -19
- wandb/apis/public/artifacts.py +259 -270
- wandb/apis/public/registries/_utils.py +40 -54
- wandb/apis/public/registries/registries_search.py +70 -85
- wandb/apis/public/registries/registry.py +173 -156
- wandb/apis/public/runs.py +27 -6
- wandb/apis/public/utils.py +43 -20
- wandb/automations/_generated/create_automation.py +2 -2
- wandb/automations/_generated/create_generic_webhook_integration.py +4 -4
- wandb/automations/_generated/delete_automation.py +2 -2
- wandb/automations/_generated/fragments.py +31 -52
- wandb/automations/_generated/generic_webhook_integrations_by_entity.py +3 -3
- wandb/automations/_generated/get_automations.py +3 -3
- wandb/automations/_generated/get_automations_by_entity.py +3 -3
- wandb/automations/_generated/input_types.py +9 -9
- wandb/automations/_generated/integrations_by_entity.py +3 -3
- wandb/automations/_generated/operations.py +6 -6
- wandb/automations/_generated/slack_integrations_by_entity.py +3 -3
- wandb/automations/_generated/update_automation.py +2 -2
- wandb/automations/_utils.py +3 -3
- wandb/automations/actions.py +3 -3
- wandb/automations/automations.py +6 -5
- wandb/bin/gpu_stats.exe +0 -0
- wandb/bin/wandb-core +0 -0
- wandb/cli/beta.py +8 -2
- wandb/cli/beta_leet.py +2 -1
- wandb/cli/beta_sync.py +1 -1
- wandb/errors/term.py +8 -8
- wandb/jupyter.py +0 -51
- wandb/old/settings.py +6 -6
- wandb/proto/v3/wandb_internal_pb2.py +351 -352
- wandb/proto/v3/wandb_server_pb2.py +38 -37
- wandb/proto/v3/wandb_settings_pb2.py +2 -2
- wandb/proto/v3/wandb_sync_pb2.py +19 -6
- wandb/proto/v4/wandb_internal_pb2.py +351 -352
- wandb/proto/v4/wandb_server_pb2.py +38 -37
- wandb/proto/v4/wandb_settings_pb2.py +2 -2
- wandb/proto/v4/wandb_sync_pb2.py +10 -6
- wandb/proto/v5/wandb_internal_pb2.py +351 -352
- wandb/proto/v5/wandb_server_pb2.py +38 -37
- wandb/proto/v5/wandb_settings_pb2.py +2 -2
- wandb/proto/v5/wandb_sync_pb2.py +10 -6
- wandb/proto/v6/wandb_internal_pb2.py +351 -352
- wandb/proto/v6/wandb_server_pb2.py +38 -37
- wandb/proto/v6/wandb_settings_pb2.py +2 -2
- wandb/proto/v6/wandb_sync_pb2.py +10 -6
- wandb/sdk/artifacts/_generated/__init__.py +96 -40
- wandb/sdk/artifacts/_generated/add_aliases.py +3 -3
- wandb/sdk/artifacts/_generated/add_artifact_collection_tags.py +26 -0
- wandb/sdk/artifacts/_generated/artifact_by_id.py +2 -2
- wandb/sdk/artifacts/_generated/artifact_by_name.py +3 -3
- wandb/sdk/artifacts/_generated/artifact_collection_membership_file_urls.py +27 -8
- wandb/sdk/artifacts/_generated/artifact_collection_membership_files.py +27 -8
- wandb/sdk/artifacts/_generated/artifact_created_by.py +7 -20
- wandb/sdk/artifacts/_generated/artifact_file_urls.py +19 -6
- wandb/sdk/artifacts/_generated/artifact_membership_by_name.py +26 -0
- wandb/sdk/artifacts/_generated/artifact_type.py +5 -5
- wandb/sdk/artifacts/_generated/artifact_used_by.py +8 -17
- wandb/sdk/artifacts/_generated/artifact_version_files.py +19 -8
- wandb/sdk/artifacts/_generated/delete_aliases.py +3 -3
- wandb/sdk/artifacts/_generated/delete_artifact.py +4 -4
- wandb/sdk/artifacts/_generated/delete_artifact_collection_tags.py +23 -0
- wandb/sdk/artifacts/_generated/delete_artifact_portfolio.py +4 -4
- wandb/sdk/artifacts/_generated/delete_artifact_sequence.py +4 -4
- wandb/sdk/artifacts/_generated/delete_registry.py +21 -0
- wandb/sdk/artifacts/_generated/fetch_artifact_manifest.py +8 -20
- wandb/sdk/artifacts/_generated/fetch_linked_artifacts.py +13 -35
- wandb/sdk/artifacts/_generated/fetch_org_info_from_entity.py +28 -0
- wandb/sdk/artifacts/_generated/fetch_registries.py +18 -8
- wandb/sdk/{projects → artifacts}/_generated/fetch_registry.py +4 -4
- wandb/sdk/artifacts/_generated/fragments.py +183 -333
- wandb/sdk/artifacts/_generated/input_types.py +133 -7
- wandb/sdk/artifacts/_generated/link_artifact.py +5 -5
- wandb/sdk/artifacts/_generated/operations.py +1053 -548
- wandb/sdk/artifacts/_generated/project_artifact_collection.py +9 -77
- wandb/sdk/artifacts/_generated/project_artifact_collections.py +21 -9
- wandb/sdk/artifacts/_generated/project_artifact_type.py +3 -3
- wandb/sdk/artifacts/_generated/project_artifact_types.py +19 -6
- wandb/sdk/artifacts/_generated/project_artifacts.py +7 -8
- wandb/sdk/artifacts/_generated/registry_collections.py +21 -9
- wandb/sdk/artifacts/_generated/registry_versions.py +20 -9
- wandb/sdk/artifacts/_generated/rename_registry.py +25 -0
- wandb/sdk/artifacts/_generated/run_input_artifacts.py +5 -9
- wandb/sdk/artifacts/_generated/run_output_artifacts.py +5 -9
- wandb/sdk/artifacts/_generated/type_info.py +2 -2
- wandb/sdk/artifacts/_generated/unlink_artifact.py +3 -5
- wandb/sdk/artifacts/_generated/update_artifact.py +3 -3
- wandb/sdk/artifacts/_generated/update_artifact_collection_type.py +28 -0
- wandb/sdk/artifacts/_generated/update_artifact_portfolio.py +7 -16
- wandb/sdk/artifacts/_generated/update_artifact_sequence.py +7 -16
- wandb/sdk/artifacts/_generated/upsert_registry.py +25 -0
- wandb/sdk/artifacts/_gqlutils.py +170 -6
- wandb/sdk/artifacts/_models/__init__.py +9 -0
- wandb/sdk/artifacts/_models/artifact_collection.py +109 -0
- wandb/sdk/artifacts/_models/manifest.py +26 -0
- wandb/sdk/artifacts/_models/pagination.py +26 -0
- wandb/sdk/artifacts/_models/registry.py +100 -0
- wandb/sdk/artifacts/_validators.py +45 -27
- wandb/sdk/artifacts/artifact.py +220 -215
- wandb/sdk/artifacts/artifact_file_cache.py +1 -1
- wandb/sdk/artifacts/artifact_manifest.py +37 -32
- wandb/sdk/artifacts/artifact_manifest_entry.py +80 -125
- wandb/sdk/artifacts/artifact_manifests/artifact_manifest_v1.py +43 -61
- wandb/sdk/artifacts/storage_handlers/gcs_handler.py +8 -6
- wandb/sdk/data_types/image.py +2 -2
- wandb/sdk/interface/interface.py +72 -64
- wandb/sdk/interface/interface_queue.py +27 -18
- wandb/sdk/interface/interface_shared.py +61 -23
- wandb/sdk/interface/interface_sock.py +9 -5
- wandb/sdk/internal/_generated/server_features_query.py +4 -4
- wandb/sdk/launch/inputs/schema.py +13 -10
- wandb/sdk/lib/apikey.py +8 -12
- wandb/sdk/lib/asyncio_compat.py +1 -1
- wandb/sdk/lib/asyncio_manager.py +5 -5
- wandb/sdk/lib/console_capture.py +38 -30
- wandb/sdk/lib/progress.py +159 -64
- wandb/sdk/lib/retry.py +3 -2
- wandb/sdk/lib/service/service_connection.py +2 -2
- wandb/sdk/lib/wb_logging.py +2 -1
- wandb/sdk/mailbox/mailbox.py +1 -1
- wandb/sdk/wandb_init.py +10 -13
- wandb/sdk/wandb_run.py +9 -46
- wandb/sdk/wandb_settings.py +102 -19
- {wandb-0.22.2.dist-info → wandb-0.22.3.dist-info}/METADATA +2 -1
- {wandb-0.22.2.dist-info → wandb-0.22.3.dist-info}/RECORD +135 -134
- wandb/sdk/artifacts/_generated/artifact_via_membership_by_name.py +0 -26
- wandb/sdk/artifacts/_generated/create_artifact_collection_tag_assignments.py +0 -36
- wandb/sdk/artifacts/_generated/delete_artifact_collection_tag_assignments.py +0 -25
- wandb/sdk/artifacts/_generated/move_artifact_collection.py +0 -35
- wandb/sdk/projects/_generated/__init__.py +0 -26
- wandb/sdk/projects/_generated/delete_project.py +0 -22
- wandb/sdk/projects/_generated/enums.py +0 -4
- wandb/sdk/projects/_generated/fragments.py +0 -41
- wandb/sdk/projects/_generated/input_types.py +0 -13
- wandb/sdk/projects/_generated/operations.py +0 -88
- wandb/sdk/projects/_generated/rename_project.py +0 -27
- wandb/sdk/projects/_generated/upsert_registry_project.py +0 -27
- {wandb-0.22.2.dist-info → wandb-0.22.3.dist-info}/WHEEL +0 -0
- {wandb-0.22.2.dist-info → wandb-0.22.3.dist-info}/entry_points.txt +0 -0
- {wandb-0.22.2.dist-info → wandb-0.22.3.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,14 +1,11 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
from enum import Enum
|
|
4
|
-
from functools import lru_cache
|
|
5
|
-
from typing import TYPE_CHECKING, Any,
|
|
4
|
+
from functools import lru_cache, partial
|
|
5
|
+
from typing import TYPE_CHECKING, Any, Collection
|
|
6
6
|
|
|
7
7
|
from wandb._strutils import ensureprefix
|
|
8
|
-
from wandb.sdk.artifacts._validators import
|
|
9
|
-
REGISTRY_PREFIX,
|
|
10
|
-
validate_artifact_types_list,
|
|
11
|
-
)
|
|
8
|
+
from wandb.sdk.artifacts._validators import REGISTRY_PREFIX, validate_artifact_types
|
|
12
9
|
|
|
13
10
|
if TYPE_CHECKING:
|
|
14
11
|
from wandb_gql import Client
|
|
@@ -24,12 +21,35 @@ class Visibility(str, Enum):
|
|
|
24
21
|
|
|
25
22
|
@classmethod
|
|
26
23
|
def _missing_(cls, value: object) -> Any:
|
|
27
|
-
|
|
24
|
+
# Allow instantiation from enum names too (e.g. "organization" or "restricted")
|
|
25
|
+
return cls.__members__.get(value)
|
|
28
26
|
|
|
27
|
+
@classmethod
|
|
28
|
+
def from_gql(cls, value: str) -> Visibility:
|
|
29
|
+
"""Convert a GraphQL `visibility` value to a Visibility enum."""
|
|
30
|
+
try:
|
|
31
|
+
return cls(value)
|
|
32
|
+
except ValueError:
|
|
33
|
+
expected = ",".join(repr(e.value) for e in cls)
|
|
34
|
+
raise ValueError(
|
|
35
|
+
f"Invalid visibility {value!r} from backend. Expected one of: {expected}"
|
|
36
|
+
) from None
|
|
29
37
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
)
|
|
38
|
+
@classmethod
|
|
39
|
+
def from_python(cls, name: str) -> Visibility:
|
|
40
|
+
"""Convert a visibility string (e.g. user-provided or python default value) to a Visibility enum."""
|
|
41
|
+
try:
|
|
42
|
+
return cls(name)
|
|
43
|
+
except ValueError:
|
|
44
|
+
expected = ",".join(repr(e.name) for e in cls)
|
|
45
|
+
raise ValueError(
|
|
46
|
+
f"Invalid visibility {name!r}. Expected one of: {expected}"
|
|
47
|
+
) from None
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def prepare_artifact_types_input(
|
|
51
|
+
artifact_types: Collection[str] | None,
|
|
52
|
+
) -> list[dict[str, str]] | None:
|
|
33
53
|
"""Format the artifact types for the GQL input.
|
|
34
54
|
|
|
35
55
|
Args:
|
|
@@ -38,39 +58,9 @@ def format_gql_artifact_types_input(
|
|
|
38
58
|
Returns:
|
|
39
59
|
The artifact types for the GQL input.
|
|
40
60
|
"""
|
|
41
|
-
if artifact_types
|
|
42
|
-
return []
|
|
43
|
-
return
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
def gql_to_registry_visibility(
|
|
47
|
-
visibility: str,
|
|
48
|
-
) -> Literal["organization", "restricted"]:
|
|
49
|
-
"""Convert the GQL visibility to the registry visibility.
|
|
50
|
-
|
|
51
|
-
Args:
|
|
52
|
-
visibility: The GQL visibility.
|
|
53
|
-
|
|
54
|
-
Returns:
|
|
55
|
-
The registry visibility.
|
|
56
|
-
"""
|
|
57
|
-
try:
|
|
58
|
-
return Visibility(visibility).name
|
|
59
|
-
except ValueError:
|
|
60
|
-
raise ValueError(f"Invalid visibility: {visibility!r} from backend")
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
def registry_visibility_to_gql(
|
|
64
|
-
visibility: Literal["organization", "restricted"],
|
|
65
|
-
) -> str:
|
|
66
|
-
"""Convert the registry visibility to the GQL visibility."""
|
|
67
|
-
try:
|
|
68
|
-
return Visibility[visibility].value
|
|
69
|
-
except LookupError:
|
|
70
|
-
allowed_str = ", ".join(map(repr, (e.name for e in Visibility)))
|
|
71
|
-
raise ValueError(
|
|
72
|
-
f"Invalid visibility: {visibility!r}. Must be one of: {allowed_str}"
|
|
73
|
-
)
|
|
61
|
+
if artifact_types:
|
|
62
|
+
return [{"name": typ} for typ in validate_artifact_types(artifact_types)]
|
|
63
|
+
return None
|
|
74
64
|
|
|
75
65
|
|
|
76
66
|
def ensure_registry_prefix_on_names(query: Any, in_name: bool = False) -> Any:
|
|
@@ -81,25 +71,21 @@ def ensure_registry_prefix_on_names(query: Any, in_name: bool = False) -> Any:
|
|
|
81
71
|
EX: {"name": "model"} -> {"name": "wandb-registry-model"}
|
|
82
72
|
"""
|
|
83
73
|
if isinstance((txt := query), str):
|
|
84
|
-
if in_name
|
|
85
|
-
|
|
86
|
-
return txt
|
|
87
|
-
if isinstance((dct := query), Mapping):
|
|
74
|
+
return ensureprefix(txt, REGISTRY_PREFIX) if in_name else txt
|
|
75
|
+
if isinstance((dct := query), dict):
|
|
88
76
|
new_dict = {}
|
|
89
77
|
for key, obj in dct.items():
|
|
90
|
-
if key == "
|
|
91
|
-
new_dict[key] = ensure_registry_prefix_on_names(obj, in_name=True)
|
|
92
|
-
elif key == "$regex":
|
|
78
|
+
if key == "$regex":
|
|
93
79
|
# For regex operator, we skip transformation of its value.
|
|
94
80
|
new_dict[key] = obj
|
|
81
|
+
elif key == "name":
|
|
82
|
+
new_dict[key] = ensure_registry_prefix_on_names(obj, in_name=True)
|
|
95
83
|
else:
|
|
96
84
|
# For any other key, propagate the in_name and skip_transform flags as-is.
|
|
97
85
|
new_dict[key] = ensure_registry_prefix_on_names(obj, in_name=in_name)
|
|
98
86
|
return new_dict
|
|
99
|
-
if isinstance((
|
|
100
|
-
return list(
|
|
101
|
-
map(lambda x: ensure_registry_prefix_on_names(x, in_name=in_name), objs)
|
|
102
|
-
)
|
|
87
|
+
if isinstance((seq := query), (list, tuple)):
|
|
88
|
+
return list(map(partial(ensure_registry_prefix_on_names, in_name=in_name), seq))
|
|
103
89
|
return query
|
|
104
90
|
|
|
105
91
|
|
|
@@ -5,33 +5,38 @@ from __future__ import annotations
|
|
|
5
5
|
import json
|
|
6
6
|
from typing import TYPE_CHECKING, Any
|
|
7
7
|
|
|
8
|
-
from pydantic import ValidationError
|
|
8
|
+
from pydantic import PositiveInt, ValidationError
|
|
9
9
|
from typing_extensions import override
|
|
10
10
|
from wandb_gql import gql
|
|
11
11
|
|
|
12
12
|
from wandb._analytics import tracked
|
|
13
13
|
from wandb.apis.paginator import Paginator
|
|
14
|
+
from wandb.apis.public.artifacts import ArtifactCollection
|
|
14
15
|
from wandb.apis.public.utils import gql_compat
|
|
15
16
|
from wandb.sdk.artifacts._generated import (
|
|
16
17
|
FETCH_REGISTRIES_GQL,
|
|
17
18
|
REGISTRY_COLLECTIONS_GQL,
|
|
18
19
|
REGISTRY_VERSIONS_GQL,
|
|
19
|
-
ArtifactCollectionType,
|
|
20
20
|
FetchRegistries,
|
|
21
|
-
RegistriesPage,
|
|
22
21
|
RegistryCollections,
|
|
23
|
-
RegistryCollectionsPage,
|
|
24
22
|
RegistryVersions,
|
|
25
|
-
RegistryVersionsPage,
|
|
26
23
|
)
|
|
27
24
|
from wandb.sdk.artifacts._gqlutils import omit_artifact_fields
|
|
28
|
-
from wandb.sdk.artifacts.
|
|
25
|
+
from wandb.sdk.artifacts._models.pagination import (
|
|
26
|
+
ArtifactMembershipConnection,
|
|
27
|
+
RegistryCollectionConnection,
|
|
28
|
+
RegistryConnection,
|
|
29
|
+
)
|
|
30
|
+
from wandb.sdk.artifacts._validators import (
|
|
31
|
+
SOURCE_COLLECTION_TYPENAME,
|
|
32
|
+
FullArtifactPath,
|
|
33
|
+
remove_registry_prefix,
|
|
34
|
+
)
|
|
29
35
|
|
|
30
36
|
from ._utils import ensure_registry_prefix_on_names
|
|
31
37
|
|
|
32
38
|
if TYPE_CHECKING:
|
|
33
|
-
from
|
|
34
|
-
|
|
39
|
+
from wandb.apis.public import RetryingClient
|
|
35
40
|
from wandb.sdk.artifacts.artifact import Artifact
|
|
36
41
|
|
|
37
42
|
|
|
@@ -40,15 +45,14 @@ class Registries(Paginator):
|
|
|
40
45
|
|
|
41
46
|
QUERY = gql(FETCH_REGISTRIES_GQL)
|
|
42
47
|
|
|
43
|
-
last_response:
|
|
44
|
-
_last_org_entity: str | None
|
|
48
|
+
last_response: RegistryConnection | None
|
|
45
49
|
|
|
46
50
|
def __init__(
|
|
47
51
|
self,
|
|
48
|
-
client:
|
|
52
|
+
client: RetryingClient,
|
|
49
53
|
organization: str,
|
|
50
54
|
filter: dict[str, Any] | None = None,
|
|
51
|
-
per_page:
|
|
55
|
+
per_page: PositiveInt = 100,
|
|
52
56
|
):
|
|
53
57
|
self.client = client
|
|
54
58
|
self.organization = organization
|
|
@@ -57,11 +61,8 @@ class Registries(Paginator):
|
|
|
57
61
|
"organization": organization,
|
|
58
62
|
"filters": json.dumps(self.filter),
|
|
59
63
|
}
|
|
60
|
-
|
|
61
64
|
super().__init__(client, variables, per_page)
|
|
62
65
|
|
|
63
|
-
self._last_org_entity = None
|
|
64
|
-
|
|
65
66
|
def __next__(self):
|
|
66
67
|
# Implement custom next since its possible to load empty pages because of auth
|
|
67
68
|
self.index += 1
|
|
@@ -71,22 +72,28 @@ class Registries(Paginator):
|
|
|
71
72
|
return self.objects[self.index]
|
|
72
73
|
|
|
73
74
|
@tracked
|
|
74
|
-
def collections(
|
|
75
|
+
def collections(
|
|
76
|
+
self, filter: dict[str, Any] | None = None, per_page: PositiveInt = 100
|
|
77
|
+
) -> Collections:
|
|
75
78
|
return Collections(
|
|
76
79
|
client=self.client,
|
|
77
80
|
organization=self.organization,
|
|
78
81
|
registry_filter=self.filter,
|
|
79
82
|
collection_filter=filter,
|
|
83
|
+
per_page=per_page,
|
|
80
84
|
)
|
|
81
85
|
|
|
82
86
|
@tracked
|
|
83
|
-
def versions(
|
|
87
|
+
def versions(
|
|
88
|
+
self, filter: dict[str, Any] | None = None, per_page: PositiveInt = 100
|
|
89
|
+
) -> Versions:
|
|
84
90
|
return Versions(
|
|
85
91
|
client=self.client,
|
|
86
92
|
organization=self.organization,
|
|
87
93
|
registry_filter=self.filter,
|
|
88
94
|
collection_filter=None,
|
|
89
95
|
artifact_filter=filter,
|
|
96
|
+
per_page=per_page,
|
|
90
97
|
)
|
|
91
98
|
|
|
92
99
|
@property
|
|
@@ -97,15 +104,11 @@ class Registries(Paginator):
|
|
|
97
104
|
|
|
98
105
|
@property
|
|
99
106
|
def more(self):
|
|
100
|
-
|
|
101
|
-
return True
|
|
102
|
-
return self.last_response.page_info.has_next_page
|
|
107
|
+
return (conn := self.last_response) is None or conn.has_next
|
|
103
108
|
|
|
104
109
|
@property
|
|
105
110
|
def cursor(self):
|
|
106
|
-
if self.last_response
|
|
107
|
-
return None
|
|
108
|
-
return self.last_response.page_info.end_cursor
|
|
111
|
+
return conn.next_cursor if (conn := self.last_response) else None
|
|
109
112
|
|
|
110
113
|
@override
|
|
111
114
|
def _update_response(self) -> None:
|
|
@@ -117,45 +120,43 @@ class Registries(Paginator):
|
|
|
117
120
|
)
|
|
118
121
|
|
|
119
122
|
try:
|
|
120
|
-
|
|
121
|
-
self.last_response =
|
|
122
|
-
self._last_org_entity = org_entity.name
|
|
123
|
+
conn = org_entity.projects
|
|
124
|
+
self.last_response = RegistryConnection.model_validate(conn)
|
|
123
125
|
except (LookupError, AttributeError, ValidationError) as e:
|
|
124
126
|
raise ValueError("Unexpected response data") from e
|
|
125
127
|
|
|
126
128
|
def convert_objects(self):
|
|
127
129
|
from wandb.apis.public.registries.registry import Registry
|
|
128
130
|
|
|
129
|
-
if
|
|
131
|
+
if self.last_response is None:
|
|
130
132
|
return []
|
|
131
133
|
|
|
132
|
-
nodes = (e.node for e in self.last_response.edges)
|
|
133
134
|
return [
|
|
134
135
|
Registry(
|
|
135
136
|
client=self.client,
|
|
136
137
|
organization=self.organization,
|
|
137
|
-
entity=
|
|
138
|
+
entity=node.entity.name,
|
|
138
139
|
name=remove_registry_prefix(node.name),
|
|
139
|
-
attrs=node
|
|
140
|
+
attrs=node,
|
|
140
141
|
)
|
|
141
|
-
for node in nodes
|
|
142
|
+
for node in self.last_response.nodes()
|
|
142
143
|
]
|
|
143
144
|
|
|
144
145
|
|
|
145
|
-
class Collections(Paginator[
|
|
146
|
+
class Collections(Paginator[ArtifactCollection]):
|
|
146
147
|
"""An lazy iterator of `ArtifactCollection` objects in a Registry."""
|
|
147
148
|
|
|
148
149
|
QUERY = gql(REGISTRY_COLLECTIONS_GQL)
|
|
149
150
|
|
|
150
|
-
last_response:
|
|
151
|
+
last_response: RegistryCollectionConnection | None
|
|
151
152
|
|
|
152
153
|
def __init__(
|
|
153
154
|
self,
|
|
154
|
-
client:
|
|
155
|
+
client: RetryingClient,
|
|
155
156
|
organization: str,
|
|
156
157
|
registry_filter: dict[str, Any] | None = None,
|
|
157
158
|
collection_filter: dict[str, Any] | None = None,
|
|
158
|
-
per_page:
|
|
159
|
+
per_page: PositiveInt = 100,
|
|
159
160
|
):
|
|
160
161
|
self.client = client
|
|
161
162
|
self.organization = organization
|
|
@@ -166,7 +167,6 @@ class Collections(Paginator["ArtifactCollection"]):
|
|
|
166
167
|
"registryFilter": json.dumps(f) if (f := registry_filter) else None,
|
|
167
168
|
"collectionFilter": json.dumps(f) if (f := collection_filter) else None,
|
|
168
169
|
"organization": organization,
|
|
169
|
-
"collectionTypes": [ArtifactCollectionType.PORTFOLIO],
|
|
170
170
|
"perPage": per_page,
|
|
171
171
|
}
|
|
172
172
|
|
|
@@ -181,48 +181,42 @@ class Collections(Paginator["ArtifactCollection"]):
|
|
|
181
181
|
return self.objects[self.index]
|
|
182
182
|
|
|
183
183
|
@tracked
|
|
184
|
-
def versions(
|
|
184
|
+
def versions(
|
|
185
|
+
self, filter: dict[str, Any] | None = None, per_page: PositiveInt = 100
|
|
186
|
+
) -> Versions:
|
|
185
187
|
return Versions(
|
|
186
188
|
client=self.client,
|
|
187
189
|
organization=self.organization,
|
|
188
190
|
registry_filter=self.registry_filter,
|
|
189
191
|
collection_filter=self.collection_filter,
|
|
190
192
|
artifact_filter=filter,
|
|
193
|
+
per_page=per_page,
|
|
191
194
|
)
|
|
192
195
|
|
|
193
196
|
@property
|
|
194
197
|
def length(self):
|
|
195
|
-
if self.last_response
|
|
196
|
-
return None
|
|
197
|
-
return self.last_response.total_count
|
|
198
|
+
return conn.total_count if (conn := self.last_response) else None
|
|
198
199
|
|
|
199
200
|
@property
|
|
200
201
|
def more(self):
|
|
201
|
-
|
|
202
|
-
return True
|
|
203
|
-
return self.last_response.page_info.has_next_page
|
|
202
|
+
return (conn := self.last_response) is None or conn.has_next
|
|
204
203
|
|
|
205
204
|
@property
|
|
206
205
|
def cursor(self):
|
|
207
|
-
if self.last_response
|
|
208
|
-
return None
|
|
209
|
-
return self.last_response.page_info.end_cursor
|
|
206
|
+
return conn.next_cursor if (conn := self.last_response) else None
|
|
210
207
|
|
|
211
208
|
@override
|
|
212
209
|
def _update_response(self) -> None:
|
|
213
210
|
data = self.client.execute(self.QUERY, variable_values=self.variables)
|
|
214
211
|
result = RegistryCollections.model_validate(data)
|
|
215
|
-
if not (
|
|
216
|
-
(org_data := result.organization)
|
|
217
|
-
and (org_entity_data := org_data.org_entity)
|
|
218
|
-
):
|
|
212
|
+
if not ((org := result.organization) and (org_entity := org.org_entity)):
|
|
219
213
|
raise ValueError(
|
|
220
214
|
f"Organization {self.organization!r} not found. Please verify the organization name is correct."
|
|
221
215
|
)
|
|
222
216
|
|
|
223
217
|
try:
|
|
224
|
-
|
|
225
|
-
self.last_response =
|
|
218
|
+
conn = org_entity.artifact_collections
|
|
219
|
+
self.last_response = RegistryCollectionConnection.model_validate(conn)
|
|
226
220
|
except (LookupError, AttributeError, ValidationError) as e:
|
|
227
221
|
raise ValueError("Unexpected response data") from e
|
|
228
222
|
|
|
@@ -232,36 +226,36 @@ class Collections(Paginator["ArtifactCollection"]):
|
|
|
232
226
|
if self.last_response is None:
|
|
233
227
|
return []
|
|
234
228
|
|
|
235
|
-
nodes = (e.node for e in self.last_response.edges)
|
|
236
229
|
return [
|
|
237
230
|
ArtifactCollection(
|
|
238
231
|
client=self.client,
|
|
239
|
-
entity=project.entity.name,
|
|
240
|
-
project=project.name,
|
|
232
|
+
entity=node.project.entity.name,
|
|
233
|
+
project=node.project.name,
|
|
241
234
|
name=node.name,
|
|
242
|
-
type=node.
|
|
235
|
+
type=node.type.name,
|
|
243
236
|
organization=self.organization,
|
|
244
|
-
attrs=node
|
|
245
|
-
is_sequence=False,
|
|
237
|
+
attrs=node,
|
|
246
238
|
)
|
|
247
|
-
for node in nodes
|
|
248
|
-
|
|
239
|
+
for node in self.last_response.nodes()
|
|
240
|
+
# We don't _expect_ any registry collections to be
|
|
241
|
+
# ArtifactSequences, but defensively filter them out anyway.
|
|
242
|
+
if node.project and (node.typename__ != SOURCE_COLLECTION_TYPENAME)
|
|
249
243
|
]
|
|
250
244
|
|
|
251
245
|
|
|
252
246
|
class Versions(Paginator["Artifact"]):
|
|
253
247
|
"""An lazy iterator of `Artifact` objects in a Registry."""
|
|
254
248
|
|
|
255
|
-
last_response:
|
|
249
|
+
last_response: ArtifactMembershipConnection | None
|
|
256
250
|
|
|
257
251
|
def __init__(
|
|
258
252
|
self,
|
|
259
|
-
client:
|
|
253
|
+
client: RetryingClient,
|
|
260
254
|
organization: str,
|
|
261
255
|
registry_filter: dict[str, Any] | None = None,
|
|
262
256
|
collection_filter: dict[str, Any] | None = None,
|
|
263
257
|
artifact_filter: dict[str, Any] | None = None,
|
|
264
|
-
per_page:
|
|
258
|
+
per_page: PositiveInt = 100,
|
|
265
259
|
):
|
|
266
260
|
self.client = client
|
|
267
261
|
self.organization = organization
|
|
@@ -298,31 +292,24 @@ class Versions(Paginator["Artifact"]):
|
|
|
298
292
|
|
|
299
293
|
@property
|
|
300
294
|
def more(self) -> bool:
|
|
301
|
-
|
|
302
|
-
return True
|
|
303
|
-
return self.last_response.page_info.has_next_page
|
|
295
|
+
return (conn := self.last_response) is None or conn.has_next
|
|
304
296
|
|
|
305
297
|
@property
|
|
306
298
|
def cursor(self) -> str | None:
|
|
307
|
-
if self.last_response
|
|
308
|
-
return None
|
|
309
|
-
return self.last_response.page_info.end_cursor
|
|
299
|
+
return conn.next_cursor if (conn := self.last_response) else None
|
|
310
300
|
|
|
311
301
|
@override
|
|
312
302
|
def _update_response(self) -> None:
|
|
313
303
|
data = self.client.execute(self.QUERY, variable_values=self.variables)
|
|
314
304
|
result = RegistryVersions.model_validate(data)
|
|
315
|
-
if not (
|
|
316
|
-
(org_data := result.organization)
|
|
317
|
-
and (org_entity_data := org_data.org_entity)
|
|
318
|
-
):
|
|
305
|
+
if not ((org := result.organization) and (org_entity := org.org_entity)):
|
|
319
306
|
raise ValueError(
|
|
320
307
|
f"Organization {self.organization!r} not found. Please verify the organization name is correct."
|
|
321
308
|
)
|
|
322
309
|
|
|
323
310
|
try:
|
|
324
|
-
|
|
325
|
-
self.last_response =
|
|
311
|
+
conn = org_entity.artifact_memberships
|
|
312
|
+
self.last_response = ArtifactMembershipConnection.model_validate(conn)
|
|
326
313
|
except (LookupError, AttributeError, ValidationError) as e:
|
|
327
314
|
raise ValueError("Unexpected response data") from e
|
|
328
315
|
|
|
@@ -331,23 +318,21 @@ class Versions(Paginator["Artifact"]):
|
|
|
331
318
|
|
|
332
319
|
if self.last_response is None:
|
|
333
320
|
return []
|
|
334
|
-
|
|
335
|
-
nodes = (e.node for e in self.last_response.edges)
|
|
336
321
|
return [
|
|
337
|
-
Artifact.
|
|
338
|
-
|
|
322
|
+
Artifact._from_membership(
|
|
323
|
+
membership=membership,
|
|
324
|
+
target=FullArtifactPath(
|
|
339
325
|
prefix=project.entity.name,
|
|
340
326
|
project=project.name,
|
|
341
|
-
name=f"{collection.name}:v{
|
|
327
|
+
name=f"{collection.name}:v{version_idx}",
|
|
342
328
|
),
|
|
343
|
-
attrs=artifact,
|
|
344
329
|
client=self.client,
|
|
345
|
-
aliases=[alias.alias for alias in node.aliases],
|
|
346
330
|
)
|
|
347
|
-
for
|
|
331
|
+
for membership in self.last_response.nodes()
|
|
348
332
|
if (
|
|
349
|
-
(collection :=
|
|
333
|
+
(collection := membership.artifact_collection)
|
|
350
334
|
and (project := collection.project)
|
|
351
|
-
and
|
|
335
|
+
and membership.artifact
|
|
336
|
+
and (version_idx := membership.version_index) is not None
|
|
352
337
|
)
|
|
353
338
|
]
|