wandb 0.22.1__py3-none-win32.whl → 0.22.3__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 +7 -4
 - 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 +23 -3
 - wandb/cli/beta_leet.py +75 -0
 - wandb/cli/beta_sync.py +1 -1
 - wandb/cli/cli.py +34 -7
 - wandb/errors/term.py +8 -8
 - wandb/jupyter.py +0 -51
 - wandb/old/settings.py +6 -6
 - wandb/proto/v3/wandb_api_pb2.py +86 -0
 - 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_api_pb2.py +37 -0
 - 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_api_pb2.py +38 -0
 - 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_api_pb2.py +48 -0
 - 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/proto/wandb_api_pb2.py +18 -0
 - wandb/proto/wandb_generate_proto.py +1 -0
 - 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 +249 -244
 - wandb/sdk/artifacts/artifact_file_cache.py +1 -1
 - wandb/sdk/artifacts/artifact_manifest.py +37 -32
 - wandb/sdk/artifacts/artifact_manifest_entry.py +82 -133
 - wandb/sdk/artifacts/artifact_manifests/artifact_manifest_v1.py +43 -61
 - wandb/sdk/artifacts/storage_handler.py +18 -12
 - wandb/sdk/artifacts/storage_handlers/azure_handler.py +11 -6
 - wandb/sdk/artifacts/storage_handlers/gcs_handler.py +17 -12
 - wandb/sdk/artifacts/storage_handlers/http_handler.py +9 -4
 - wandb/sdk/artifacts/storage_handlers/local_file_handler.py +10 -6
 - wandb/sdk/artifacts/storage_handlers/multi_handler.py +5 -4
 - wandb/sdk/artifacts/storage_handlers/s3_handler.py +10 -8
 - wandb/sdk/artifacts/storage_handlers/tracking_handler.py +6 -4
 - wandb/sdk/artifacts/storage_handlers/wb_artifact_handler.py +24 -21
 - wandb/sdk/artifacts/storage_handlers/wb_local_artifact_handler.py +4 -2
 - wandb/sdk/artifacts/storage_policies/_multipart.py +187 -0
 - wandb/sdk/artifacts/storage_policies/wandb_storage_policy.py +61 -242
 - wandb/sdk/artifacts/storage_policy.py +25 -12
 - wandb/sdk/data_types/image.py +2 -2
 - wandb/sdk/data_types/object_3d.py +67 -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/internal/job_builder.py +27 -10
 - wandb/sdk/internal/sender.py +4 -1
 - wandb/sdk/launch/create_job.py +2 -1
 - 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 +151 -125
 - 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 +11 -14
 - wandb/sdk/wandb_run.py +14 -48
 - wandb/sdk/wandb_settings.py +114 -30
 - {wandb-0.22.1.dist-info → wandb-0.22.3.dist-info}/METADATA +2 -1
 - {wandb-0.22.1.dist-info → wandb-0.22.3.dist-info}/RECORD +154 -146
 - 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.1.dist-info → wandb-0.22.3.dist-info}/WHEEL +0 -0
 - {wandb-0.22.1.dist-info → wandb-0.22.3.dist-info}/entry_points.txt +0 -0
 - {wandb-0.22.1.dist-info → wandb-0.22.3.dist-info}/licenses/LICENSE +0 -0
 
    
        wandb/apis/public/artifacts.py
    CHANGED
    
    | 
         @@ -7,14 +7,25 @@ collections. 
     | 
|
| 
       7 
7 
     | 
    
         
             
            from __future__ import annotations
         
     | 
| 
       8 
8 
     | 
    
         | 
| 
       9 
9 
     | 
    
         
             
            import json
         
     | 
| 
       10 
     | 
    
         
            -
            import re
         
     | 
| 
       11 
10 
     | 
    
         
             
            from copy import copy
         
     | 
| 
       12 
     | 
    
         
            -
            from typing import  
     | 
| 
      
 11 
     | 
    
         
            +
            from typing import (
         
     | 
| 
      
 12 
     | 
    
         
            +
                TYPE_CHECKING,
         
     | 
| 
      
 13 
     | 
    
         
            +
                Any,
         
     | 
| 
      
 14 
     | 
    
         
            +
                ClassVar,
         
     | 
| 
      
 15 
     | 
    
         
            +
                Collection,
         
     | 
| 
      
 16 
     | 
    
         
            +
                Iterable,
         
     | 
| 
      
 17 
     | 
    
         
            +
                List,
         
     | 
| 
      
 18 
     | 
    
         
            +
                Literal,
         
     | 
| 
      
 19 
     | 
    
         
            +
                Mapping,
         
     | 
| 
      
 20 
     | 
    
         
            +
                Sequence,
         
     | 
| 
      
 21 
     | 
    
         
            +
            )
         
     | 
| 
       13 
22 
     | 
    
         | 
| 
       14 
23 
     | 
    
         
             
            from typing_extensions import override
         
     | 
| 
       15 
     | 
    
         
            -
            from wandb_gql import  
     | 
| 
      
 24 
     | 
    
         
            +
            from wandb_gql import gql
         
     | 
| 
       16 
25 
     | 
    
         | 
| 
       17 
26 
     | 
    
         
             
            import wandb
         
     | 
| 
      
 27 
     | 
    
         
            +
            from wandb._iterutils import always_list
         
     | 
| 
      
 28 
     | 
    
         
            +
            from wandb._pydantic import ConnectionWithTotal, Edge
         
     | 
| 
       18 
29 
     | 
    
         
             
            from wandb._strutils import nameof
         
     | 
| 
       19 
30 
     | 
    
         
             
            from wandb.apis import public
         
     | 
| 
       20 
31 
     | 
    
         
             
            from wandb.apis.normalize import normalize_exceptions
         
     | 
| 
         @@ -23,13 +34,12 @@ from wandb.errors.term import termlog 
     | 
|
| 
       23 
34 
     | 
    
         
             
            from wandb.proto.wandb_deprecated import Deprecated
         
     | 
| 
       24 
35 
     | 
    
         
             
            from wandb.proto.wandb_internal_pb2 import ServerFeature
         
     | 
| 
       25 
36 
     | 
    
         
             
            from wandb.sdk.artifacts._generated import (
         
     | 
| 
      
 37 
     | 
    
         
            +
                ADD_ARTIFACT_COLLECTION_TAGS_GQL,
         
     | 
| 
       26 
38 
     | 
    
         
             
                ARTIFACT_COLLECTION_MEMBERSHIP_FILES_GQL,
         
     | 
| 
       27 
39 
     | 
    
         
             
                ARTIFACT_VERSION_FILES_GQL,
         
     | 
| 
       28 
     | 
    
         
            -
                 
     | 
| 
       29 
     | 
    
         
            -
                DELETE_ARTIFACT_COLLECTION_TAG_ASSIGNMENTS_GQL,
         
     | 
| 
      
 40 
     | 
    
         
            +
                DELETE_ARTIFACT_COLLECTION_TAGS_GQL,
         
     | 
| 
       30 
41 
     | 
    
         
             
                DELETE_ARTIFACT_PORTFOLIO_GQL,
         
     | 
| 
       31 
42 
     | 
    
         
             
                DELETE_ARTIFACT_SEQUENCE_GQL,
         
     | 
| 
       32 
     | 
    
         
            -
                MOVE_ARTIFACT_COLLECTION_GQL,
         
     | 
| 
       33 
43 
     | 
    
         
             
                PROJECT_ARTIFACT_COLLECTION_GQL,
         
     | 
| 
       34 
44 
     | 
    
         
             
                PROJECT_ARTIFACT_COLLECTIONS_GQL,
         
     | 
| 
       35 
45 
     | 
    
         
             
                PROJECT_ARTIFACT_TYPE_GQL,
         
     | 
| 
         @@ -37,36 +47,42 @@ from wandb.sdk.artifacts._generated import ( 
     | 
|
| 
       37 
47 
     | 
    
         
             
                PROJECT_ARTIFACTS_GQL,
         
     | 
| 
       38 
48 
     | 
    
         
             
                RUN_INPUT_ARTIFACTS_GQL,
         
     | 
| 
       39 
49 
     | 
    
         
             
                RUN_OUTPUT_ARTIFACTS_GQL,
         
     | 
| 
      
 50 
     | 
    
         
            +
                UPDATE_ARTIFACT_COLLECTION_TYPE_GQL,
         
     | 
| 
       40 
51 
     | 
    
         
             
                UPDATE_ARTIFACT_PORTFOLIO_GQL,
         
     | 
| 
       41 
52 
     | 
    
         
             
                UPDATE_ARTIFACT_SEQUENCE_GQL,
         
     | 
| 
      
 53 
     | 
    
         
            +
                ArtifactCollectionFragment,
         
     | 
| 
       42 
54 
     | 
    
         
             
                ArtifactCollectionMembershipFiles,
         
     | 
| 
       43 
     | 
    
         
            -
                 
     | 
| 
       44 
     | 
    
         
            -
                ArtifactsFragment,
         
     | 
| 
      
 55 
     | 
    
         
            +
                ArtifactFragment,
         
     | 
| 
       45 
56 
     | 
    
         
             
                ArtifactTypeFragment,
         
     | 
| 
       46 
     | 
    
         
            -
                ArtifactTypesFragment,
         
     | 
| 
       47 
57 
     | 
    
         
             
                ArtifactVersionFiles,
         
     | 
| 
       48 
     | 
    
         
            -
                 
     | 
| 
      
 58 
     | 
    
         
            +
                CreateArtifactCollectionTagAssignmentsInput,
         
     | 
| 
      
 59 
     | 
    
         
            +
                DeleteArtifactCollectionTagAssignmentsInput,
         
     | 
| 
      
 60 
     | 
    
         
            +
                MoveArtifactSequenceInput,
         
     | 
| 
       49 
61 
     | 
    
         
             
                ProjectArtifactCollection,
         
     | 
| 
       50 
62 
     | 
    
         
             
                ProjectArtifactCollections,
         
     | 
| 
       51 
63 
     | 
    
         
             
                ProjectArtifacts,
         
     | 
| 
       52 
64 
     | 
    
         
             
                ProjectArtifactType,
         
     | 
| 
       53 
65 
     | 
    
         
             
                ProjectArtifactTypes,
         
     | 
| 
       54 
     | 
    
         
            -
                 
     | 
| 
       55 
     | 
    
         
            -
                 
     | 
| 
      
 66 
     | 
    
         
            +
                UpdateArtifactPortfolioInput,
         
     | 
| 
      
 67 
     | 
    
         
            +
                UpdateArtifactSequenceInput,
         
     | 
| 
       56 
68 
     | 
    
         
             
            )
         
     | 
| 
       57 
69 
     | 
    
         
             
            from wandb.sdk.artifacts._gqlutils import omit_artifact_fields
         
     | 
| 
       58 
     | 
    
         
            -
            from wandb.sdk.artifacts. 
     | 
| 
       59 
     | 
    
         
            -
             
     | 
| 
       60 
     | 
    
         
            -
                 
     | 
| 
       61 
     | 
    
         
            -
                 
     | 
| 
       62 
     | 
    
         
            -
                 
     | 
| 
      
 70 
     | 
    
         
            +
            from wandb.sdk.artifacts._models import ArtifactCollectionData
         
     | 
| 
      
 71 
     | 
    
         
            +
            from wandb.sdk.artifacts._models.pagination import (
         
     | 
| 
      
 72 
     | 
    
         
            +
                ArtifactCollectionConnection,
         
     | 
| 
      
 73 
     | 
    
         
            +
                ArtifactFileConnection,
         
     | 
| 
      
 74 
     | 
    
         
            +
                ArtifactTypeConnection,
         
     | 
| 
      
 75 
     | 
    
         
            +
                RunArtifactConnection,
         
     | 
| 
       63 
76 
     | 
    
         
             
            )
         
     | 
| 
      
 77 
     | 
    
         
            +
            from wandb.sdk.artifacts._validators import FullArtifactPath, validate_artifact_type
         
     | 
| 
       64 
78 
     | 
    
         
             
            from wandb.sdk.internal.internal_api import Api as InternalApi
         
     | 
| 
       65 
79 
     | 
    
         
             
            from wandb.sdk.lib import deprecate
         
     | 
| 
       66 
80 
     | 
    
         | 
| 
       67 
81 
     | 
    
         
             
            from .utils import gql_compat
         
     | 
| 
       68 
82 
     | 
    
         | 
| 
       69 
83 
     | 
    
         
             
            if TYPE_CHECKING:
         
     | 
| 
      
 84 
     | 
    
         
            +
                from wandb_gql import Client
         
     | 
| 
      
 85 
     | 
    
         
            +
             
     | 
| 
       70 
86 
     | 
    
         
             
                from wandb.sdk.artifacts.artifact import Artifact
         
     | 
| 
       71 
87 
     | 
    
         | 
| 
       72 
88 
     | 
    
         
             
                from . import RetryingClient, Run
         
     | 
| 
         @@ -80,7 +96,7 @@ class ArtifactTypes(Paginator["ArtifactType"]): 
     | 
|
| 
       80 
96 
     | 
    
         | 
| 
       81 
97 
     | 
    
         
             
                QUERY = gql(PROJECT_ARTIFACT_TYPES_GQL)
         
     | 
| 
       82 
98 
     | 
    
         | 
| 
       83 
     | 
    
         
            -
                last_response:  
     | 
| 
      
 99 
     | 
    
         
            +
                last_response: ArtifactTypeConnection | None
         
     | 
| 
       84 
100 
     | 
    
         | 
| 
       85 
101 
     | 
    
         
             
                def __init__(
         
     | 
| 
       86 
102 
     | 
    
         
             
                    self,
         
     | 
| 
         @@ -108,7 +124,7 @@ class ArtifactTypes(Paginator["ArtifactType"]): 
     | 
|
| 
       108 
124 
     | 
    
         
             
                    if not ((proj := result.project) and (conn := proj.artifact_types)):
         
     | 
| 
       109 
125 
     | 
    
         
             
                        raise ValueError(f"Unable to parse {nameof(type(self))!r} response data")
         
     | 
| 
       110 
126 
     | 
    
         | 
| 
       111 
     | 
    
         
            -
                    self.last_response =  
     | 
| 
      
 127 
     | 
    
         
            +
                    self.last_response = ArtifactTypeConnection.model_validate(conn)
         
     | 
| 
       112 
128 
     | 
    
         | 
| 
       113 
129 
     | 
    
         
             
                @property
         
     | 
| 
       114 
130 
     | 
    
         
             
                def _length(self) -> None:
         
     | 
| 
         @@ -125,9 +141,7 @@ class ArtifactTypes(Paginator["ArtifactType"]): 
     | 
|
| 
       125 
141 
     | 
    
         | 
| 
       126 
142 
     | 
    
         
             
                    <!-- lazydoc-ignore: internal -->
         
     | 
| 
       127 
143 
     | 
    
         
             
                    """
         
     | 
| 
       128 
     | 
    
         
            -
                     
     | 
| 
       129 
     | 
    
         
            -
                        return True
         
     | 
| 
       130 
     | 
    
         
            -
                    return self.last_response.page_info.has_next_page
         
     | 
| 
      
 144 
     | 
    
         
            +
                    return (conn := self.last_response) is None or conn.has_next
         
     | 
| 
       131 
145 
     | 
    
         | 
| 
       132 
146 
     | 
    
         
             
                @property
         
     | 
| 
       133 
147 
     | 
    
         
             
                def cursor(self) -> str | None:
         
     | 
| 
         @@ -135,9 +149,7 @@ class ArtifactTypes(Paginator["ArtifactType"]): 
     | 
|
| 
       135 
149 
     | 
    
         | 
| 
       136 
150 
     | 
    
         
             
                    <!-- lazydoc-ignore: internal -->
         
     | 
| 
       137 
151 
     | 
    
         
             
                    """
         
     | 
| 
       138 
     | 
    
         
            -
                    if self.last_response  
     | 
| 
       139 
     | 
    
         
            -
                        return None
         
     | 
| 
       140 
     | 
    
         
            -
                    return self.last_response.edges[-1].cursor
         
     | 
| 
      
 152 
     | 
    
         
            +
                    return conn.next_cursor if (conn := self.last_response) else None
         
     | 
| 
       141 
153 
     | 
    
         | 
| 
       142 
154 
     | 
    
         
             
                def update_variables(self) -> None:
         
     | 
| 
       143 
155 
     | 
    
         
             
                    """Update the cursor variable for pagination.
         
     | 
| 
         @@ -160,10 +172,9 @@ class ArtifactTypes(Paginator["ArtifactType"]): 
     | 
|
| 
       160 
172 
     | 
    
         
             
                            entity=self.entity,
         
     | 
| 
       161 
173 
     | 
    
         
             
                            project=self.project,
         
     | 
| 
       162 
174 
     | 
    
         
             
                            type_name=node.name,
         
     | 
| 
       163 
     | 
    
         
            -
                            attrs=node 
     | 
| 
      
 175 
     | 
    
         
            +
                            attrs=node,
         
     | 
| 
       164 
176 
     | 
    
         
             
                        )
         
     | 
| 
       165 
     | 
    
         
            -
                        for  
     | 
| 
       166 
     | 
    
         
            -
                        if edge.node and (node := ArtifactTypeFragment.model_validate(edge.node))
         
     | 
| 
      
 177 
     | 
    
         
            +
                        for node in self.last_response.nodes()
         
     | 
| 
       167 
178 
     | 
    
         
             
                    ]
         
     | 
| 
       168 
179 
     | 
    
         | 
| 
       169 
180 
     | 
    
         | 
| 
         @@ -181,51 +192,50 @@ class ArtifactType: 
     | 
|
| 
       181 
192 
     | 
    
         
             
                <!-- lazydoc-ignore-init: internal -->
         
     | 
| 
       182 
193 
     | 
    
         
             
                """
         
     | 
| 
       183 
194 
     | 
    
         | 
| 
      
 195 
     | 
    
         
            +
                _attrs: ArtifactTypeFragment
         
     | 
| 
      
 196 
     | 
    
         
            +
             
     | 
| 
       184 
197 
     | 
    
         
             
                def __init__(
         
     | 
| 
       185 
198 
     | 
    
         
             
                    self,
         
     | 
| 
       186 
199 
     | 
    
         
             
                    client: Client,
         
     | 
| 
       187 
200 
     | 
    
         
             
                    entity: str,
         
     | 
| 
       188 
201 
     | 
    
         
             
                    project: str,
         
     | 
| 
       189 
202 
     | 
    
         
             
                    type_name: str,
         
     | 
| 
       190 
     | 
    
         
            -
                    attrs:  
     | 
| 
      
 203 
     | 
    
         
            +
                    attrs: ArtifactTypeFragment | None = None,
         
     | 
| 
       191 
204 
     | 
    
         
             
                ):
         
     | 
| 
       192 
205 
     | 
    
         
             
                    self.client = client
         
     | 
| 
       193 
206 
     | 
    
         
             
                    self.entity = entity
         
     | 
| 
       194 
207 
     | 
    
         
             
                    self.project = project
         
     | 
| 
       195 
208 
     | 
    
         
             
                    self.type = type_name
         
     | 
| 
       196 
     | 
    
         
            -
                    self._attrs = attrs
         
     | 
| 
       197 
     | 
    
         
            -
                    if self._attrs is None:
         
     | 
| 
       198 
     | 
    
         
            -
                        self.load()
         
     | 
| 
       199 
209 
     | 
    
         | 
| 
       200 
     | 
    
         
            -
             
     | 
| 
      
 210 
     | 
    
         
            +
                    # FIXME: Make this lazy, so we don't (re-)fetch the attributes until they are needed
         
     | 
| 
      
 211 
     | 
    
         
            +
                    self._attrs = ArtifactTypeFragment.model_validate(attrs or self.load())
         
     | 
| 
      
 212 
     | 
    
         
            +
             
     | 
| 
      
 213 
     | 
    
         
            +
                def load(self) -> ArtifactTypeFragment:
         
     | 
| 
       201 
214 
     | 
    
         
             
                    """Load the artifact type attributes from W&B.
         
     | 
| 
       202 
215 
     | 
    
         | 
| 
       203 
216 
     | 
    
         
             
                    <!-- lazydoc-ignore: internal -->
         
     | 
| 
       204 
217 
     | 
    
         
             
                    """
         
     | 
| 
       205 
     | 
    
         
            -
                     
     | 
| 
       206 
     | 
    
         
            -
             
     | 
| 
       207 
     | 
    
         
            -
                         
     | 
| 
       208 
     | 
    
         
            -
             
     | 
| 
       209 
     | 
    
         
            -
             
     | 
| 
       210 
     | 
    
         
            -
             
     | 
| 
       211 
     | 
    
         
            -
             
     | 
| 
       212 
     | 
    
         
            -
                    )
         
     | 
| 
      
 218 
     | 
    
         
            +
                    gql_op = gql(PROJECT_ARTIFACT_TYPE_GQL)
         
     | 
| 
      
 219 
     | 
    
         
            +
                    gql_vars = {
         
     | 
| 
      
 220 
     | 
    
         
            +
                        "entityName": self.entity,
         
     | 
| 
      
 221 
     | 
    
         
            +
                        "projectName": self.project,
         
     | 
| 
      
 222 
     | 
    
         
            +
                        "artifactTypeName": self.type,
         
     | 
| 
      
 223 
     | 
    
         
            +
                    }
         
     | 
| 
      
 224 
     | 
    
         
            +
                    data = self.client.execute(gql_op, variable_values=gql_vars)
         
     | 
| 
       213 
225 
     | 
    
         
             
                    result = ProjectArtifactType.model_validate(data)
         
     | 
| 
       214 
226 
     | 
    
         
             
                    if not ((proj := result.project) and (artifact_type := proj.artifact_type)):
         
     | 
| 
       215 
     | 
    
         
            -
                        raise ValueError(f"Could not find artifact type {self.type}")
         
     | 
| 
       216 
     | 
    
         
            -
             
     | 
| 
       217 
     | 
    
         
            -
                    self._attrs = artifact_type.model_dump(exclude_unset=True)
         
     | 
| 
       218 
     | 
    
         
            -
                    return self._attrs
         
     | 
| 
      
 227 
     | 
    
         
            +
                        raise ValueError(f"Could not find artifact type {self.type!r}")
         
     | 
| 
      
 228 
     | 
    
         
            +
                    return ArtifactTypeFragment.model_validate(artifact_type)
         
     | 
| 
       219 
229 
     | 
    
         | 
| 
       220 
230 
     | 
    
         
             
                @property
         
     | 
| 
       221 
231 
     | 
    
         
             
                def id(self) -> str:
         
     | 
| 
       222 
232 
     | 
    
         
             
                    """The unique identifier of the artifact type."""
         
     | 
| 
       223 
     | 
    
         
            -
                    return self._attrs 
     | 
| 
      
 233 
     | 
    
         
            +
                    return self._attrs.id
         
     | 
| 
       224 
234 
     | 
    
         | 
| 
       225 
235 
     | 
    
         
             
                @property
         
     | 
| 
       226 
236 
     | 
    
         
             
                def name(self) -> str:
         
     | 
| 
       227 
237 
     | 
    
         
             
                    """The name of the artifact type."""
         
     | 
| 
       228 
     | 
    
         
            -
                    return self._attrs 
     | 
| 
      
 238 
     | 
    
         
            +
                    return self._attrs.name
         
     | 
| 
       229 
239 
     | 
    
         | 
| 
       230 
240 
     | 
    
         
             
                @normalize_exceptions
         
     | 
| 
       231 
241 
     | 
    
         
             
                def collections(self, per_page: int = 50) -> ArtifactCollections:
         
     | 
| 
         @@ -235,7 +245,12 @@ class ArtifactType: 
     | 
|
| 
       235 
245 
     | 
    
         
             
                        per_page (int): The number of artifact collections to fetch per page.
         
     | 
| 
       236 
246 
     | 
    
         
             
                            Default is 50.
         
     | 
| 
       237 
247 
     | 
    
         
             
                    """
         
     | 
| 
       238 
     | 
    
         
            -
                    return ArtifactCollections( 
     | 
| 
      
 248 
     | 
    
         
            +
                    return ArtifactCollections(
         
     | 
| 
      
 249 
     | 
    
         
            +
                        self.client,
         
     | 
| 
      
 250 
     | 
    
         
            +
                        entity=self.entity,
         
     | 
| 
      
 251 
     | 
    
         
            +
                        project=self.project,
         
     | 
| 
      
 252 
     | 
    
         
            +
                        type_name=self.type,
         
     | 
| 
      
 253 
     | 
    
         
            +
                    )
         
     | 
| 
       239 
254 
     | 
    
         | 
| 
       240 
255 
     | 
    
         
             
                def collection(self, name: str) -> ArtifactCollection:
         
     | 
| 
       241 
256 
     | 
    
         
             
                    """Get a specific artifact collection by name.
         
     | 
| 
         @@ -244,7 +259,11 @@ class ArtifactType: 
     | 
|
| 
       244 
259 
     | 
    
         
             
                        name (str): The name of the artifact collection to retrieve.
         
     | 
| 
       245 
260 
     | 
    
         
             
                    """
         
     | 
| 
       246 
261 
     | 
    
         
             
                    return ArtifactCollection(
         
     | 
| 
       247 
     | 
    
         
            -
                        self.client, 
     | 
| 
      
 262 
     | 
    
         
            +
                        self.client,
         
     | 
| 
      
 263 
     | 
    
         
            +
                        entity=self.entity,
         
     | 
| 
      
 264 
     | 
    
         
            +
                        project=self.project,
         
     | 
| 
      
 265 
     | 
    
         
            +
                        name=name,
         
     | 
| 
      
 266 
     | 
    
         
            +
                        type=self.type,
         
     | 
| 
       248 
267 
     | 
    
         
             
                    )
         
     | 
| 
       249 
268 
     | 
    
         | 
| 
       250 
269 
     | 
    
         
             
                def __repr__(self) -> str:
         
     | 
| 
         @@ -264,7 +283,7 @@ class ArtifactCollections(SizedPaginator["ArtifactCollection"]): 
     | 
|
| 
       264 
283 
     | 
    
         
             
                <!-- lazydoc-ignore-init: internal -->
         
     | 
| 
       265 
284 
     | 
    
         
             
                """
         
     | 
| 
       266 
285 
     | 
    
         | 
| 
       267 
     | 
    
         
            -
                last_response:  
     | 
| 
      
 286 
     | 
    
         
            +
                last_response: ArtifactCollectionConnection | None
         
     | 
| 
       268 
287 
     | 
    
         | 
| 
       269 
288 
     | 
    
         
             
                def __init__(
         
     | 
| 
       270 
289 
     | 
    
         
             
                    self,
         
     | 
| 
         @@ -278,11 +297,7 @@ class ArtifactCollections(SizedPaginator["ArtifactCollection"]): 
     | 
|
| 
       278 
297 
     | 
    
         
             
                    self.project = project
         
     | 
| 
       279 
298 
     | 
    
         
             
                    self.type_name = type_name
         
     | 
| 
       280 
299 
     | 
    
         | 
| 
       281 
     | 
    
         
            -
                     
     | 
| 
       282 
     | 
    
         
            -
                        "entityName": entity,
         
     | 
| 
       283 
     | 
    
         
            -
                        "projectName": project,
         
     | 
| 
       284 
     | 
    
         
            -
                        "artifactTypeName": type_name,
         
     | 
| 
       285 
     | 
    
         
            -
                    }
         
     | 
| 
      
 300 
     | 
    
         
            +
                    variables = {"entity": entity, "project": project, "artifactType": type_name}
         
     | 
| 
       286 
301 
     | 
    
         | 
| 
       287 
302 
     | 
    
         
             
                    if server_supports_artifact_collections_gql_edges(client):
         
     | 
| 
       288 
303 
     | 
    
         
             
                        rename_fields = None
         
     | 
| 
         @@ -293,7 +308,7 @@ class ArtifactCollections(SizedPaginator["ArtifactCollection"]): 
     | 
|
| 
       293 
308 
     | 
    
         
             
                        PROJECT_ARTIFACT_COLLECTIONS_GQL, rename_fields=rename_fields
         
     | 
| 
       294 
309 
     | 
    
         
             
                    )
         
     | 
| 
       295 
310 
     | 
    
         | 
| 
       296 
     | 
    
         
            -
                    super().__init__(client,  
     | 
| 
      
 311 
     | 
    
         
            +
                    super().__init__(client, variables, per_page)
         
     | 
| 
       297 
312 
     | 
    
         | 
| 
       298 
313 
     | 
    
         
             
                @override
         
     | 
| 
       299 
314 
     | 
    
         
             
                def _update_response(self) -> None:
         
     | 
| 
         @@ -304,12 +319,12 @@ class ArtifactCollections(SizedPaginator["ArtifactCollection"]): 
     | 
|
| 
       304 
319 
     | 
    
         
             
                    # Extract the inner `*Connection` result for faster/easier access.
         
     | 
| 
       305 
320 
     | 
    
         
             
                    if not (
         
     | 
| 
       306 
321 
     | 
    
         
             
                        (proj := result.project)
         
     | 
| 
       307 
     | 
    
         
            -
                        and ( 
     | 
| 
       308 
     | 
    
         
            -
                        and (conn :=  
     | 
| 
      
 322 
     | 
    
         
            +
                        and (artifact_type := proj.artifact_type)
         
     | 
| 
      
 323 
     | 
    
         
            +
                        and (conn := artifact_type.artifact_collections)
         
     | 
| 
       309 
324 
     | 
    
         
             
                    ):
         
     | 
| 
       310 
325 
     | 
    
         
             
                        raise ValueError(f"Unable to parse {nameof(type(self))!r} response data")
         
     | 
| 
       311 
326 
     | 
    
         | 
| 
       312 
     | 
    
         
            -
                    self.last_response =  
     | 
| 
      
 327 
     | 
    
         
            +
                    self.last_response = ArtifactCollectionConnection.model_validate(conn)
         
     | 
| 
       313 
328 
     | 
    
         | 
| 
       314 
329 
     | 
    
         
             
                @property
         
     | 
| 
       315 
330 
     | 
    
         
             
                def _length(self) -> int:
         
     | 
| 
         @@ -322,24 +337,20 @@ class ArtifactCollections(SizedPaginator["ArtifactCollection"]): 
     | 
|
| 
       322 
337 
     | 
    
         
             
                    return self.last_response.total_count
         
     | 
| 
       323 
338 
     | 
    
         | 
| 
       324 
339 
     | 
    
         
             
                @property
         
     | 
| 
       325 
     | 
    
         
            -
                def more(self):
         
     | 
| 
      
 340 
     | 
    
         
            +
                def more(self) -> bool:
         
     | 
| 
       326 
341 
     | 
    
         
             
                    """Returns whether there are more artifacts to fetch.
         
     | 
| 
       327 
342 
     | 
    
         | 
| 
       328 
343 
     | 
    
         
             
                    <!-- lazydoc-ignore: internal -->
         
     | 
| 
       329 
344 
     | 
    
         
             
                    """
         
     | 
| 
       330 
     | 
    
         
            -
                     
     | 
| 
       331 
     | 
    
         
            -
                        return True
         
     | 
| 
       332 
     | 
    
         
            -
                    return self.last_response.page_info.has_next_page
         
     | 
| 
      
 345 
     | 
    
         
            +
                    return (conn := self.last_response) is None or conn.has_next
         
     | 
| 
       333 
346 
     | 
    
         | 
| 
       334 
347 
     | 
    
         
             
                @property
         
     | 
| 
       335 
     | 
    
         
            -
                def cursor(self):
         
     | 
| 
      
 348 
     | 
    
         
            +
                def cursor(self) -> str | None:
         
     | 
| 
       336 
349 
     | 
    
         
             
                    """Returns the cursor for the next page of results.
         
     | 
| 
       337 
350 
     | 
    
         | 
| 
       338 
351 
     | 
    
         
             
                    <!-- lazydoc-ignore: internal -->
         
     | 
| 
       339 
352 
     | 
    
         
             
                    """
         
     | 
| 
       340 
     | 
    
         
            -
                    if self.last_response  
     | 
| 
       341 
     | 
    
         
            -
                        return None
         
     | 
| 
       342 
     | 
    
         
            -
                    return self.last_response.edges[-1].cursor
         
     | 
| 
      
 353 
     | 
    
         
            +
                    return conn.next_cursor if (conn := self.last_response) else None
         
     | 
| 
       343 
354 
     | 
    
         | 
| 
       344 
355 
     | 
    
         
             
                def update_variables(self) -> None:
         
     | 
| 
       345 
356 
     | 
    
         
             
                    """Update the cursor variable for pagination.
         
     | 
| 
         @@ -358,13 +369,14 @@ class ArtifactCollections(SizedPaginator["ArtifactCollection"]): 
     | 
|
| 
       358 
369 
     | 
    
         
             
                    return [
         
     | 
| 
       359 
370 
     | 
    
         
             
                        ArtifactCollection(
         
     | 
| 
       360 
371 
     | 
    
         
             
                            client=self.client,
         
     | 
| 
       361 
     | 
    
         
            -
                            entity= 
     | 
| 
       362 
     | 
    
         
            -
                            project= 
     | 
| 
      
 372 
     | 
    
         
            +
                            entity=node.project.entity.name,
         
     | 
| 
      
 373 
     | 
    
         
            +
                            project=node.project.name,
         
     | 
| 
       363 
374 
     | 
    
         
             
                            name=node.name,
         
     | 
| 
       364 
     | 
    
         
            -
                            type= 
     | 
| 
      
 375 
     | 
    
         
            +
                            type=node.type.name,
         
     | 
| 
      
 376 
     | 
    
         
            +
                            attrs=node,
         
     | 
| 
       365 
377 
     | 
    
         
             
                        )
         
     | 
| 
       366 
     | 
    
         
            -
                        for  
     | 
| 
       367 
     | 
    
         
            -
                        if  
     | 
| 
      
 378 
     | 
    
         
            +
                        for node in self.last_response.nodes()
         
     | 
| 
      
 379 
     | 
    
         
            +
                        if node.project
         
     | 
| 
       368 
380 
     | 
    
         
             
                    ]
         
     | 
| 
       369 
381 
     | 
    
         | 
| 
       370 
382 
     | 
    
         | 
| 
         @@ -385,6 +397,12 @@ class ArtifactCollection: 
     | 
|
| 
       385 
397 
     | 
    
         
             
                <!-- lazydoc-ignore-init: internal -->
         
     | 
| 
       386 
398 
     | 
    
         
             
                """
         
     | 
| 
       387 
399 
     | 
    
         | 
| 
      
 400 
     | 
    
         
            +
                _saved: ArtifactCollectionData
         
     | 
| 
      
 401 
     | 
    
         
            +
                """The saved artifact collection data as last fetched from the W&B server."""
         
     | 
| 
      
 402 
     | 
    
         
            +
             
     | 
| 
      
 403 
     | 
    
         
            +
                _current: ArtifactCollectionData
         
     | 
| 
      
 404 
     | 
    
         
            +
                """The local, editable artifact collection data."""
         
     | 
| 
      
 405 
     | 
    
         
            +
             
     | 
| 
       388 
406 
     | 
    
         
             
                def __init__(
         
     | 
| 
       389 
407 
     | 
    
         
             
                    self,
         
     | 
| 
       390 
408 
     | 
    
         
             
                    client: Client,
         
     | 
| 
         @@ -393,32 +411,34 @@ class ArtifactCollection: 
     | 
|
| 
       393 
411 
     | 
    
         
             
                    name: str,
         
     | 
| 
       394 
412 
     | 
    
         
             
                    type: str,
         
     | 
| 
       395 
413 
     | 
    
         
             
                    organization: str | None = None,
         
     | 
| 
       396 
     | 
    
         
            -
                    attrs:  
     | 
| 
       397 
     | 
    
         
            -
                    is_sequence: bool | None = None,
         
     | 
| 
      
 414 
     | 
    
         
            +
                    attrs: ArtifactCollectionFragment | None = None,
         
     | 
| 
       398 
415 
     | 
    
         
             
                ):
         
     | 
| 
       399 
416 
     | 
    
         
             
                    self.client = client
         
     | 
| 
       400 
     | 
    
         
            -
             
     | 
| 
       401 
     | 
    
         
            -
                     
     | 
| 
       402 
     | 
    
         
            -
                    self. 
     | 
| 
       403 
     | 
    
         
            -
             
     | 
| 
       404 
     | 
    
         
            -
                     
     | 
| 
       405 
     | 
    
         
            -
                     
     | 
| 
       406 
     | 
    
         
            -
                    self. 
     | 
| 
       407 
     | 
    
         
            -
                     
     | 
| 
       408 
     | 
    
         
            -
             
     | 
| 
       409 
     | 
    
         
            -
                    if (attrs is None) or (is_sequence is None):
         
     | 
| 
       410 
     | 
    
         
            -
                        self.load()
         
     | 
| 
       411 
     | 
    
         
            -
                    self._aliases = [a["node"]["alias"] for a in self._attrs["aliases"]["edges"]]
         
     | 
| 
       412 
     | 
    
         
            -
                    self._description = self._attrs["description"]
         
     | 
| 
       413 
     | 
    
         
            -
                    self._created_at = self._attrs["createdAt"]
         
     | 
| 
       414 
     | 
    
         
            -
                    self._tags = [a["node"]["name"] for a in self._attrs["tags"]["edges"]]
         
     | 
| 
       415 
     | 
    
         
            -
                    self._saved_tags = copy(self._tags)
         
     | 
| 
      
 417 
     | 
    
         
            +
             
     | 
| 
      
 418 
     | 
    
         
            +
                    # FIXME: Make this lazy, so we don't (re-)fetch the attributes until they are needed
         
     | 
| 
      
 419 
     | 
    
         
            +
                    fragment = attrs or self.load(entity, project, type, name)
         
     | 
| 
      
 420 
     | 
    
         
            +
             
     | 
| 
      
 421 
     | 
    
         
            +
                    # Separate "saved" vs "current" copies of the artifact collection data
         
     | 
| 
      
 422 
     | 
    
         
            +
                    validated = ArtifactCollectionData.from_fragment(fragment)
         
     | 
| 
      
 423 
     | 
    
         
            +
                    self._saved = validated
         
     | 
| 
      
 424 
     | 
    
         
            +
                    self._current = validated.model_copy(deep=True)
         
     | 
| 
      
 425 
     | 
    
         
            +
             
     | 
| 
       416 
426 
     | 
    
         
             
                    self.organization = organization
         
     | 
| 
       417 
427 
     | 
    
         | 
| 
       418 
428 
     | 
    
         
             
                @property
         
     | 
| 
       419 
429 
     | 
    
         
             
                def id(self) -> str:
         
     | 
| 
       420 
430 
     | 
    
         
             
                    """The unique identifier of the artifact collection."""
         
     | 
| 
       421 
     | 
    
         
            -
                    return self. 
     | 
| 
      
 431 
     | 
    
         
            +
                    return self._current.id
         
     | 
| 
      
 432 
     | 
    
         
            +
             
     | 
| 
      
 433 
     | 
    
         
            +
                @property
         
     | 
| 
      
 434 
     | 
    
         
            +
                def entity(self) -> str:
         
     | 
| 
      
 435 
     | 
    
         
            +
                    """The entity (user or team) that owns the project."""
         
     | 
| 
      
 436 
     | 
    
         
            +
                    return self._current.entity
         
     | 
| 
      
 437 
     | 
    
         
            +
             
     | 
| 
      
 438 
     | 
    
         
            +
                @property
         
     | 
| 
      
 439 
     | 
    
         
            +
                def project(self) -> str:
         
     | 
| 
      
 440 
     | 
    
         
            +
                    """The project that contains the artifact collection."""
         
     | 
| 
      
 441 
     | 
    
         
            +
                    return self._current.project
         
     | 
| 
       422 
442 
     | 
    
         | 
| 
       423 
443 
     | 
    
         
             
                @normalize_exceptions
         
     | 
| 
       424 
444 
     | 
    
         
             
                def artifacts(self, per_page: int = 50) -> Artifacts:
         
     | 
| 
         @@ -427,23 +447,26 @@ class ArtifactCollection: 
     | 
|
| 
       427 
447 
     | 
    
         
             
                        client=self.client,
         
     | 
| 
       428 
448 
     | 
    
         
             
                        entity=self.entity,
         
     | 
| 
       429 
449 
     | 
    
         
             
                        project=self.project,
         
     | 
| 
       430 
     | 
    
         
            -
                         
     | 
| 
       431 
     | 
    
         
            -
                         
     | 
| 
      
 450 
     | 
    
         
            +
                        # Use the saved name and type, since they're mutable and may have been edited locally.
         
     | 
| 
      
 451 
     | 
    
         
            +
                        collection_name=self._saved.name,
         
     | 
| 
      
 452 
     | 
    
         
            +
                        type=self._saved.type,
         
     | 
| 
       432 
453 
     | 
    
         
             
                        per_page=per_page,
         
     | 
| 
       433 
454 
     | 
    
         
             
                    )
         
     | 
| 
       434 
455 
     | 
    
         | 
| 
       435 
456 
     | 
    
         
             
                @property
         
     | 
| 
       436 
457 
     | 
    
         
             
                def aliases(self) -> list[str]:
         
     | 
| 
       437 
458 
     | 
    
         
             
                    """Artifact Collection Aliases."""
         
     | 
| 
       438 
     | 
    
         
            -
                    return self. 
     | 
| 
      
 459 
     | 
    
         
            +
                    return list(self._saved.aliases)
         
     | 
| 
       439 
460 
     | 
    
         | 
| 
       440 
461 
     | 
    
         
             
                @property
         
     | 
| 
       441 
462 
     | 
    
         
             
                def created_at(self) -> str:
         
     | 
| 
       442 
463 
     | 
    
         
             
                    """The creation date of the artifact collection."""
         
     | 
| 
       443 
     | 
    
         
            -
                    return self. 
     | 
| 
      
 464 
     | 
    
         
            +
                    return self._saved.created_at
         
     | 
| 
       444 
465 
     | 
    
         | 
| 
       445 
     | 
    
         
            -
                def load( 
     | 
| 
       446 
     | 
    
         
            -
                     
     | 
| 
      
 466 
     | 
    
         
            +
                def load(
         
     | 
| 
      
 467 
     | 
    
         
            +
                    self, entity: str, project: str, artifact_type: str, name: str
         
     | 
| 
      
 468 
     | 
    
         
            +
                ) -> ArtifactCollectionFragment:
         
     | 
| 
      
 469 
     | 
    
         
            +
                    """Fetch and return the validated artifact collection data from W&B.
         
     | 
| 
       447 
470 
     | 
    
         | 
| 
       448 
471 
     | 
    
         
             
                    <!-- lazydoc-ignore: internal -->
         
     | 
| 
       449 
472 
     | 
    
         
             
                    """
         
     | 
| 
         @@ -452,34 +475,25 @@ class ArtifactCollection: 
     | 
|
| 
       452 
475 
     | 
    
         
             
                    else:
         
     | 
| 
       453 
476 
     | 
    
         
             
                        rename_fields = {"artifactCollection": "artifactSequence"}
         
     | 
| 
       454 
477 
     | 
    
         | 
| 
       455 
     | 
    
         
            -
                     
     | 
| 
       456 
     | 
    
         
            -
                         
     | 
| 
       457 
     | 
    
         
            -
                        variable_values={
         
     | 
| 
       458 
     | 
    
         
            -
                            "entityName": self.entity,
         
     | 
| 
       459 
     | 
    
         
            -
                            "projectName": self.project,
         
     | 
| 
       460 
     | 
    
         
            -
                            "artifactTypeName": self._saved_type,
         
     | 
| 
       461 
     | 
    
         
            -
                            "artifactCollectionName": self._saved_name,
         
     | 
| 
       462 
     | 
    
         
            -
                        },
         
     | 
| 
      
 478 
     | 
    
         
            +
                    gql_op = gql_compat(
         
     | 
| 
      
 479 
     | 
    
         
            +
                        PROJECT_ARTIFACT_COLLECTION_GQL, rename_fields=rename_fields
         
     | 
| 
       463 
480 
     | 
    
         
             
                    )
         
     | 
| 
       464 
     | 
    
         
            -
             
     | 
| 
       465 
     | 
    
         
            -
             
     | 
| 
       466 
     | 
    
         
            -
             
     | 
| 
      
 481 
     | 
    
         
            +
                    gql_vars = {
         
     | 
| 
      
 482 
     | 
    
         
            +
                        "entity": entity,
         
     | 
| 
      
 483 
     | 
    
         
            +
                        "project": project,
         
     | 
| 
      
 484 
     | 
    
         
            +
                        "artifactType": artifact_type,
         
     | 
| 
      
 485 
     | 
    
         
            +
                        "name": name,
         
     | 
| 
      
 486 
     | 
    
         
            +
                    }
         
     | 
| 
      
 487 
     | 
    
         
            +
                    data = self.client.execute(gql_op, variable_values=gql_vars)
         
     | 
| 
      
 488 
     | 
    
         
            +
                    result = ProjectArtifactCollection.model_validate(data)
         
     | 
| 
       467 
489 
     | 
    
         
             
                    if not (
         
     | 
| 
       468 
490 
     | 
    
         
             
                        result.project
         
     | 
| 
       469 
491 
     | 
    
         
             
                        and (proj := result.project)
         
     | 
| 
       470 
492 
     | 
    
         
             
                        and (type_ := proj.artifact_type)
         
     | 
| 
       471 
493 
     | 
    
         
             
                        and (collection := type_.artifact_collection)
         
     | 
| 
       472 
494 
     | 
    
         
             
                    ):
         
     | 
| 
       473 
     | 
    
         
            -
                        raise ValueError(f"Could not find artifact type { 
     | 
| 
       474 
     | 
    
         
            -
             
     | 
| 
       475 
     | 
    
         
            -
                    sequence = type_.artifact_sequence
         
     | 
| 
       476 
     | 
    
         
            -
                    self._is_sequence = (
         
     | 
| 
       477 
     | 
    
         
            -
                        sequence is not None
         
     | 
| 
       478 
     | 
    
         
            -
                    ) and sequence.typename__ == SOURCE_ARTIFACT_COLLECTION_TYPE
         
     | 
| 
       479 
     | 
    
         
            -
             
     | 
| 
       480 
     | 
    
         
            -
                    if self._attrs is None:
         
     | 
| 
       481 
     | 
    
         
            -
                        self._attrs = collection.model_dump(exclude_unset=True)
         
     | 
| 
       482 
     | 
    
         
            -
                    return self._attrs
         
     | 
| 
      
 495 
     | 
    
         
            +
                        raise ValueError(f"Could not find artifact type {artifact_type!s}")
         
     | 
| 
      
 496 
     | 
    
         
            +
                    return collection
         
     | 
| 
       483 
497 
     | 
    
         | 
| 
       484 
498 
     | 
    
         
             
                @normalize_exceptions
         
     | 
| 
       485 
499 
     | 
    
         
             
                def change_type(self, new_type: str) -> None:
         
     | 
| 
         @@ -489,174 +503,178 @@ class ArtifactCollection: 
     | 
|
| 
       489 
503 
     | 
    
         
             
                        warning_message="ArtifactCollection.change_type(type) is deprecated, use ArtifactCollection.save() instead.",
         
     | 
| 
       490 
504 
     | 
    
         
             
                    )
         
     | 
| 
       491 
505 
     | 
    
         | 
| 
       492 
     | 
    
         
            -
                    if self. 
     | 
| 
      
 506 
     | 
    
         
            +
                    if (old_type := self._saved.type) != new_type:
         
     | 
| 
       493 
507 
     | 
    
         
             
                        try:
         
     | 
| 
       494 
     | 
    
         
            -
                            validate_artifact_type( 
     | 
| 
      
 508 
     | 
    
         
            +
                            validate_artifact_type(old_type, self.name)
         
     | 
| 
       495 
509 
     | 
    
         
             
                        except ValueError as e:
         
     | 
| 
       496 
510 
     | 
    
         
             
                            raise ValueError(
         
     | 
| 
       497 
     | 
    
         
            -
                                f"The current type  
     | 
| 
      
 511 
     | 
    
         
            +
                                f"The current type {old_type!r} is an internal type and cannot be changed."
         
     | 
| 
       498 
512 
     | 
    
         
             
                            ) from e
         
     | 
| 
       499 
513 
     | 
    
         | 
| 
       500 
514 
     | 
    
         
             
                    # Check that the new type is not going to conflict with internal types
         
     | 
| 
       501 
     | 
    
         
            -
                    validate_artifact_type(new_type, self.name)
         
     | 
| 
      
 515 
     | 
    
         
            +
                    new_type = validate_artifact_type(new_type, self.name)
         
     | 
| 
       502 
516 
     | 
    
         | 
| 
       503 
517 
     | 
    
         
             
                    if not self.is_sequence():
         
     | 
| 
       504 
518 
     | 
    
         
             
                        raise ValueError("Artifact collection needs to be a sequence")
         
     | 
| 
       505 
     | 
    
         
            -
             
     | 
| 
       506 
     | 
    
         
            -
             
     | 
| 
       507 
     | 
    
         
            -
             
     | 
| 
       508 
     | 
    
         
            -
                     
     | 
| 
       509 
     | 
    
         
            -
             
     | 
| 
       510 
     | 
    
         
            -
                         
     | 
| 
       511 
     | 
    
         
            -
             
     | 
| 
       512 
     | 
    
         
            -
                            "destinationArtifactTypeName": new_type,
         
     | 
| 
       513 
     | 
    
         
            -
                        },
         
     | 
| 
      
 519 
     | 
    
         
            +
             
     | 
| 
      
 520 
     | 
    
         
            +
                    termlog(f"Changing artifact collection type of {old_type!r} to {new_type!r}")
         
     | 
| 
      
 521 
     | 
    
         
            +
             
     | 
| 
      
 522 
     | 
    
         
            +
                    gql_op = gql(UPDATE_ARTIFACT_COLLECTION_TYPE_GQL)
         
     | 
| 
      
 523 
     | 
    
         
            +
                    gql_input = MoveArtifactSequenceInput(
         
     | 
| 
      
 524 
     | 
    
         
            +
                        artifact_sequence_id=self.id,
         
     | 
| 
      
 525 
     | 
    
         
            +
                        destination_artifact_type_name=new_type,
         
     | 
| 
       514 
526 
     | 
    
         
             
                    )
         
     | 
| 
       515 
     | 
    
         
            -
                    self. 
     | 
| 
       516 
     | 
    
         
            -
                    self. 
     | 
| 
      
 527 
     | 
    
         
            +
                    self.client.execute(gql_op, variable_values={"input": gql_input.model_dump()})
         
     | 
| 
      
 528 
     | 
    
         
            +
                    self._saved.type = new_type
         
     | 
| 
      
 529 
     | 
    
         
            +
                    self._current.type = new_type
         
     | 
| 
       517 
530 
     | 
    
         | 
| 
       518 
531 
     | 
    
         
             
                def is_sequence(self) -> bool:
         
     | 
| 
       519 
532 
     | 
    
         
             
                    """Return whether the artifact collection is a sequence."""
         
     | 
| 
       520 
     | 
    
         
            -
                    return self. 
     | 
| 
      
 533 
     | 
    
         
            +
                    return self._saved.is_sequence
         
     | 
| 
       521 
534 
     | 
    
         | 
| 
       522 
535 
     | 
    
         
             
                @normalize_exceptions
         
     | 
| 
       523 
536 
     | 
    
         
             
                def delete(self) -> None:
         
     | 
| 
       524 
537 
     | 
    
         
             
                    """Delete the entire artifact collection."""
         
     | 
| 
       525 
     | 
    
         
            -
                     
     | 
| 
       526 
     | 
    
         
            -
                         
     | 
| 
       527 
     | 
    
         
            -
             
     | 
| 
       528 
     | 
    
         
            -
             
     | 
| 
       529 
     | 
    
         
            -
                            else DELETE_ARTIFACT_PORTFOLIO_GQL
         
     | 
| 
       530 
     | 
    
         
            -
                        ),
         
     | 
| 
       531 
     | 
    
         
            -
                        variable_values={"id": self.id},
         
     | 
| 
      
 538 
     | 
    
         
            +
                    gql_op = gql(
         
     | 
| 
      
 539 
     | 
    
         
            +
                        DELETE_ARTIFACT_SEQUENCE_GQL
         
     | 
| 
      
 540 
     | 
    
         
            +
                        if self.is_sequence()
         
     | 
| 
      
 541 
     | 
    
         
            +
                        else DELETE_ARTIFACT_PORTFOLIO_GQL
         
     | 
| 
       532 
542 
     | 
    
         
             
                    )
         
     | 
| 
      
 543 
     | 
    
         
            +
                    self.client.execute(gql_op, variable_values={"id": self.id})
         
     | 
| 
       533 
544 
     | 
    
         | 
| 
       534 
545 
     | 
    
         
             
                @property
         
     | 
| 
       535 
     | 
    
         
            -
                def description(self) -> str:
         
     | 
| 
      
 546 
     | 
    
         
            +
                def description(self) -> str | None:
         
     | 
| 
       536 
547 
     | 
    
         
             
                    """A description of the artifact collection."""
         
     | 
| 
       537 
     | 
    
         
            -
                    return self. 
     | 
| 
      
 548 
     | 
    
         
            +
                    return self._current.description
         
     | 
| 
       538 
549 
     | 
    
         | 
| 
       539 
550 
     | 
    
         
             
                @description.setter
         
     | 
| 
       540 
551 
     | 
    
         
             
                def description(self, description: str | None) -> None:
         
     | 
| 
       541 
552 
     | 
    
         
             
                    """Set the description of the artifact collection."""
         
     | 
| 
       542 
     | 
    
         
            -
                    self. 
     | 
| 
      
 553 
     | 
    
         
            +
                    self._current.description = description
         
     | 
| 
       543 
554 
     | 
    
         | 
| 
       544 
555 
     | 
    
         
             
                @property
         
     | 
| 
       545 
556 
     | 
    
         
             
                def tags(self) -> list[str]:
         
     | 
| 
       546 
557 
     | 
    
         
             
                    """The tags associated with the artifact collection."""
         
     | 
| 
       547 
     | 
    
         
            -
                    return self. 
     | 
| 
      
 558 
     | 
    
         
            +
                    return self._current.tags
         
     | 
| 
       548 
559 
     | 
    
         | 
| 
       549 
560 
     | 
    
         
             
                @tags.setter
         
     | 
| 
       550 
     | 
    
         
            -
                def tags(self, tags:  
     | 
| 
      
 561 
     | 
    
         
            +
                def tags(self, tags: Collection[str]) -> None:
         
     | 
| 
       551 
562 
     | 
    
         
             
                    """Set the tags associated with the artifact collection."""
         
     | 
| 
       552 
     | 
    
         
            -
                     
     | 
| 
       553 
     | 
    
         
            -
                        raise ValueError(
         
     | 
| 
       554 
     | 
    
         
            -
                            "Tags must only contain alphanumeric characters or underscores separated by spaces or hyphens"
         
     | 
| 
       555 
     | 
    
         
            -
                        )
         
     | 
| 
       556 
     | 
    
         
            -
                    self._tags = tags
         
     | 
| 
      
 563 
     | 
    
         
            +
                    self._current.tags = tags
         
     | 
| 
       557 
564 
     | 
    
         | 
| 
       558 
565 
     | 
    
         
             
                @property
         
     | 
| 
       559 
566 
     | 
    
         
             
                def name(self) -> str:
         
     | 
| 
       560 
567 
     | 
    
         
             
                    """The name of the artifact collection."""
         
     | 
| 
       561 
     | 
    
         
            -
                    return self. 
     | 
| 
      
 568 
     | 
    
         
            +
                    return self._current.name
         
     | 
| 
       562 
569 
     | 
    
         | 
| 
       563 
570 
     | 
    
         
             
                @name.setter
         
     | 
| 
       564 
571 
     | 
    
         
             
                def name(self, name: str) -> None:
         
     | 
| 
       565 
572 
     | 
    
         
             
                    """Set the name of the artifact collection."""
         
     | 
| 
       566 
     | 
    
         
            -
                    self. 
     | 
| 
      
 573 
     | 
    
         
            +
                    self._current.name = name
         
     | 
| 
       567 
574 
     | 
    
         | 
| 
       568 
575 
     | 
    
         
             
                @property
         
     | 
| 
       569 
576 
     | 
    
         
             
                def type(self):
         
     | 
| 
       570 
577 
     | 
    
         
             
                    """Returns the type of the artifact collection."""
         
     | 
| 
       571 
     | 
    
         
            -
                    return self. 
     | 
| 
      
 578 
     | 
    
         
            +
                    return self._current.type
         
     | 
| 
       572 
579 
     | 
    
         | 
| 
       573 
580 
     | 
    
         
             
                @type.setter
         
     | 
| 
       574 
     | 
    
         
            -
                def type(self, type:  
     | 
| 
      
 581 
     | 
    
         
            +
                def type(self, type: str) -> None:
         
     | 
| 
       575 
582 
     | 
    
         
             
                    """Set the type of the artifact collection."""
         
     | 
| 
       576 
583 
     | 
    
         
             
                    if not self.is_sequence():
         
     | 
| 
       577 
584 
     | 
    
         
             
                        raise ValueError(
         
     | 
| 
       578 
585 
     | 
    
         
             
                            "Type can only be changed if the artifact collection is a sequence."
         
     | 
| 
       579 
586 
     | 
    
         
             
                        )
         
     | 
| 
       580 
     | 
    
         
            -
                    self. 
     | 
| 
      
 587 
     | 
    
         
            +
                    self._current.type = type
         
     | 
| 
       581 
588 
     | 
    
         | 
| 
       582 
589 
     | 
    
         
             
                def _update_collection(self) -> None:
         
     | 
| 
       583 
     | 
    
         
            -
                    self. 
     | 
| 
       584 
     | 
    
         
            -
                        gql(
         
     | 
| 
       585 
     | 
    
         
            -
             
     | 
| 
       586 
     | 
    
         
            -
                             
     | 
| 
       587 
     | 
    
         
            -
                             
     | 
| 
       588 
     | 
    
         
            -
             
     | 
| 
       589 
     | 
    
         
            -
                         
     | 
| 
       590 
     | 
    
         
            -
             
     | 
| 
       591 
     | 
    
         
            -
             
     | 
| 
       592 
     | 
    
         
            -
             
     | 
| 
       593 
     | 
    
         
            -
             
     | 
| 
       594 
     | 
    
         
            -
             
     | 
| 
       595 
     | 
    
         
            -
             
     | 
| 
      
 590 
     | 
    
         
            +
                    if self.is_sequence():
         
     | 
| 
      
 591 
     | 
    
         
            +
                        gql_op = gql(UPDATE_ARTIFACT_SEQUENCE_GQL)
         
     | 
| 
      
 592 
     | 
    
         
            +
                        gql_input = UpdateArtifactSequenceInput(
         
     | 
| 
      
 593 
     | 
    
         
            +
                            artifact_sequence_id=self.id,
         
     | 
| 
      
 594 
     | 
    
         
            +
                            name=self.name,
         
     | 
| 
      
 595 
     | 
    
         
            +
                            description=self.description,
         
     | 
| 
      
 596 
     | 
    
         
            +
                        )
         
     | 
| 
      
 597 
     | 
    
         
            +
                    else:
         
     | 
| 
      
 598 
     | 
    
         
            +
                        gql_op = gql(UPDATE_ARTIFACT_PORTFOLIO_GQL)
         
     | 
| 
      
 599 
     | 
    
         
            +
                        gql_input = UpdateArtifactPortfolioInput(
         
     | 
| 
      
 600 
     | 
    
         
            +
                            artifact_portfolio_id=self.id,
         
     | 
| 
      
 601 
     | 
    
         
            +
                            name=self.name,
         
     | 
| 
      
 602 
     | 
    
         
            +
                            description=self.description,
         
     | 
| 
      
 603 
     | 
    
         
            +
                        )
         
     | 
| 
      
 604 
     | 
    
         
            +
                    self.client.execute(gql_op, variable_values={"input": gql_input.model_dump()})
         
     | 
| 
      
 605 
     | 
    
         
            +
                    self._saved.name = self._current.name
         
     | 
| 
       596 
606 
     | 
    
         | 
| 
       597 
607 
     | 
    
         
             
                def _update_collection_type(self) -> None:
         
     | 
| 
       598 
     | 
    
         
            -
                     
     | 
| 
       599 
     | 
    
         
            -
             
     | 
| 
       600 
     | 
    
         
            -
                         
     | 
| 
       601 
     | 
    
         
            -
             
     | 
| 
       602 
     | 
    
         
            -
                            "destinationArtifactTypeName": self.type,
         
     | 
| 
       603 
     | 
    
         
            -
                        },
         
     | 
| 
      
 608 
     | 
    
         
            +
                    gql_op = gql(UPDATE_ARTIFACT_COLLECTION_TYPE_GQL)
         
     | 
| 
      
 609 
     | 
    
         
            +
                    gql_input = MoveArtifactSequenceInput(
         
     | 
| 
      
 610 
     | 
    
         
            +
                        artifact_sequence_id=self.id,
         
     | 
| 
      
 611 
     | 
    
         
            +
                        destination_artifact_type_name=self.type,
         
     | 
| 
       604 
612 
     | 
    
         
             
                    )
         
     | 
| 
       605 
     | 
    
         
            -
                    self. 
     | 
| 
       606 
     | 
    
         
            -
             
     | 
| 
       607 
     | 
    
         
            -
             
     | 
| 
       608 
     | 
    
         
            -
             
     | 
| 
       609 
     | 
    
         
            -
             
     | 
| 
       610 
     | 
    
         
            -
             
     | 
| 
       611 
     | 
    
         
            -
             
     | 
| 
       612 
     | 
    
         
            -
             
     | 
| 
       613 
     | 
    
         
            -
             
     | 
| 
       614 
     | 
    
         
            -
             
     | 
| 
       615 
     | 
    
         
            -
                        },
         
     | 
| 
      
 613 
     | 
    
         
            +
                    self.client.execute(gql_op, variable_values={"input": gql_input.model_dump()})
         
     | 
| 
      
 614 
     | 
    
         
            +
                    self._saved.type = self._current.type
         
     | 
| 
      
 615 
     | 
    
         
            +
             
     | 
| 
      
 616 
     | 
    
         
            +
                def _add_tags(self, tag_names: Iterable[str]) -> None:
         
     | 
| 
      
 617 
     | 
    
         
            +
                    gql_op = gql(ADD_ARTIFACT_COLLECTION_TAGS_GQL)
         
     | 
| 
      
 618 
     | 
    
         
            +
                    gql_input = CreateArtifactCollectionTagAssignmentsInput(
         
     | 
| 
      
 619 
     | 
    
         
            +
                        entity_name=self.entity,
         
     | 
| 
      
 620 
     | 
    
         
            +
                        project_name=self.project,
         
     | 
| 
      
 621 
     | 
    
         
            +
                        artifact_collection_name=self._saved.name,
         
     | 
| 
      
 622 
     | 
    
         
            +
                        tags=[{"tagName": tag} for tag in tag_names],
         
     | 
| 
       616 
623 
     | 
    
         
             
                    )
         
     | 
| 
       617 
     | 
    
         
            -
             
     | 
| 
       618 
     | 
    
         
            -
             
     | 
| 
       619 
     | 
    
         
            -
             
     | 
| 
       620 
     | 
    
         
            -
             
     | 
| 
       621 
     | 
    
         
            -
             
     | 
| 
       622 
     | 
    
         
            -
             
     | 
| 
       623 
     | 
    
         
            -
             
     | 
| 
       624 
     | 
    
         
            -
             
     | 
| 
       625 
     | 
    
         
            -
             
     | 
| 
       626 
     | 
    
         
            -
                        },
         
     | 
| 
      
 624 
     | 
    
         
            +
                    self.client.execute(gql_op, variable_values={"input": gql_input.model_dump()})
         
     | 
| 
      
 625 
     | 
    
         
            +
             
     | 
| 
      
 626 
     | 
    
         
            +
                def _delete_tags(self, tag_names: Iterable[str]) -> None:
         
     | 
| 
      
 627 
     | 
    
         
            +
                    gql_op = gql(DELETE_ARTIFACT_COLLECTION_TAGS_GQL)
         
     | 
| 
      
 628 
     | 
    
         
            +
                    gql_input = DeleteArtifactCollectionTagAssignmentsInput(
         
     | 
| 
      
 629 
     | 
    
         
            +
                        entity_name=self.entity,
         
     | 
| 
      
 630 
     | 
    
         
            +
                        project_name=self.project,
         
     | 
| 
      
 631 
     | 
    
         
            +
                        artifact_collection_name=self._saved.name,
         
     | 
| 
      
 632 
     | 
    
         
            +
                        tags=[{"tagName": tag} for tag in tag_names],
         
     | 
| 
       627 
633 
     | 
    
         
             
                    )
         
     | 
| 
      
 634 
     | 
    
         
            +
                    self.client.execute(gql_op, variable_values={"input": gql_input.model_dump()})
         
     | 
| 
       628 
635 
     | 
    
         | 
| 
       629 
636 
     | 
    
         
             
                @normalize_exceptions
         
     | 
| 
       630 
637 
     | 
    
         
             
                def save(self) -> None:
         
     | 
| 
       631 
638 
     | 
    
         
             
                    """Persist any changes made to the artifact collection."""
         
     | 
| 
       632 
     | 
    
         
            -
                    if self. 
     | 
| 
      
 639 
     | 
    
         
            +
                    if (old_type := self._saved.type) != (new_type := self.type):
         
     | 
| 
       633 
640 
     | 
    
         
             
                        try:
         
     | 
| 
       634 
     | 
    
         
            -
                            validate_artifact_type( 
     | 
| 
      
 641 
     | 
    
         
            +
                            validate_artifact_type(new_type, self.name)
         
     | 
| 
       635 
642 
     | 
    
         
             
                        except ValueError as e:
         
     | 
| 
       636 
     | 
    
         
            -
                             
     | 
| 
      
 643 
     | 
    
         
            +
                            reason = str(e)
         
     | 
| 
      
 644 
     | 
    
         
            +
                            raise ValueError(
         
     | 
| 
      
 645 
     | 
    
         
            +
                                f"Failed to save artifact collection {self.name!r}: {reason}"
         
     | 
| 
      
 646 
     | 
    
         
            +
                            ) from e
         
     | 
| 
       637 
647 
     | 
    
         
             
                        try:
         
     | 
| 
       638 
     | 
    
         
            -
                            validate_artifact_type( 
     | 
| 
      
 648 
     | 
    
         
            +
                            validate_artifact_type(old_type, self.name)
         
     | 
| 
       639 
649 
     | 
    
         
             
                        except ValueError as e:
         
     | 
| 
      
 650 
     | 
    
         
            +
                            reason = f"The current type {old_type!r} is an internal type and cannot be changed."
         
     | 
| 
       640 
651 
     | 
    
         
             
                            raise ValueError(
         
     | 
| 
       641 
     | 
    
         
            -
                                f"Failed to save artifact collection  
     | 
| 
       642 
     | 
    
         
            -
                                f"The current type '{self._saved_type!r}' is an internal type and cannot be changed."
         
     | 
| 
      
 652 
     | 
    
         
            +
                                f"Failed to save artifact collection {self.name!r}: {reason}"
         
     | 
| 
       643 
653 
     | 
    
         
             
                            ) from e
         
     | 
| 
       644 
654 
     | 
    
         | 
| 
      
 655 
     | 
    
         
            +
                    # FIXME: Consider consolidating the multiple GQL mutations into a single call.
         
     | 
| 
       645 
656 
     | 
    
         
             
                    self._update_collection()
         
     | 
| 
       646 
657 
     | 
    
         | 
| 
       647 
     | 
    
         
            -
                    if self.is_sequence() and ( 
     | 
| 
      
 658 
     | 
    
         
            +
                    if self.is_sequence() and (old_type != new_type):
         
     | 
| 
       648 
659 
     | 
    
         
             
                        self._update_collection_type()
         
     | 
| 
       649 
660 
     | 
    
         | 
| 
       650 
     | 
    
         
            -
                     
     | 
| 
       651 
     | 
    
         
            -
             
     | 
| 
       652 
     | 
    
         
            -
             
     | 
| 
       653 
     | 
    
         
            -
                         
     | 
| 
       654 
     | 
    
         
            -
             
     | 
| 
       655 
     | 
    
         
            -
                        self. 
     | 
| 
       656 
     | 
    
         
            -
                    self._saved_tags = copy(self._tags)
         
     | 
| 
      
 661 
     | 
    
         
            +
                    if (new_tags := set(self._current.tags)) != (old_tags := set(self._saved.tags)):
         
     | 
| 
      
 662 
     | 
    
         
            +
                        if added_tags := (new_tags - old_tags):
         
     | 
| 
      
 663 
     | 
    
         
            +
                            self._add_tags(added_tags)
         
     | 
| 
      
 664 
     | 
    
         
            +
                        if deleted_tags := (old_tags - new_tags):
         
     | 
| 
      
 665 
     | 
    
         
            +
                            self._delete_tags(deleted_tags)
         
     | 
| 
      
 666 
     | 
    
         
            +
                        self._saved.tags = copy(new_tags)
         
     | 
| 
       657 
667 
     | 
    
         | 
| 
       658 
668 
     | 
    
         
             
                def __repr__(self) -> str:
         
     | 
| 
       659 
     | 
    
         
            -
                    return f"<ArtifactCollection {self. 
     | 
| 
      
 669 
     | 
    
         
            +
                    return f"<ArtifactCollection {self.name} ({self.type})>"
         
     | 
| 
      
 670 
     | 
    
         
            +
             
     | 
| 
      
 671 
     | 
    
         
            +
             
     | 
| 
      
 672 
     | 
    
         
            +
            class _ArtifactEdge(Edge[ArtifactFragment]):
         
     | 
| 
      
 673 
     | 
    
         
            +
                version: str  # Extra field defined only on VersionedArtifactEdge
         
     | 
| 
      
 674 
     | 
    
         
            +
             
     | 
| 
      
 675 
     | 
    
         
            +
             
     | 
| 
      
 676 
     | 
    
         
            +
            class _ArtifactConnection(ConnectionWithTotal[ArtifactFragment]):
         
     | 
| 
      
 677 
     | 
    
         
            +
                edges: List[_ArtifactEdge]  # noqa: UP006
         
     | 
| 
       660 
678 
     | 
    
         | 
| 
       661 
679 
     | 
    
         | 
| 
       662 
680 
     | 
    
         
             
            class Artifacts(SizedPaginator["Artifact"]):
         
     | 
| 
         @@ -679,7 +697,7 @@ class Artifacts(SizedPaginator["Artifact"]): 
     | 
|
| 
       679 
697 
     | 
    
         
             
                <!-- lazydoc-ignore-init: internal -->
         
     | 
| 
       680 
698 
     | 
    
         
             
                """
         
     | 
| 
       681 
699 
     | 
    
         | 
| 
       682 
     | 
    
         
            -
                last_response:  
     | 
| 
      
 700 
     | 
    
         
            +
                last_response: _ArtifactConnection | None
         
     | 
| 
       683 
701 
     | 
    
         | 
| 
       684 
702 
     | 
    
         
             
                def __init__(
         
     | 
| 
       685 
703 
     | 
    
         
             
                    self,
         
     | 
| 
         @@ -698,7 +716,7 @@ class Artifacts(SizedPaginator["Artifact"]): 
     | 
|
| 
       698 
716 
     | 
    
         
             
                    self.type = type
         
     | 
| 
       699 
717 
     | 
    
         
             
                    self.project = project
         
     | 
| 
       700 
718 
     | 
    
         
             
                    self.filters = {"state": "COMMITTED"} if filters is None else filters
         
     | 
| 
       701 
     | 
    
         
            -
                    self.tags =  
     | 
| 
      
 719 
     | 
    
         
            +
                    self.tags = always_list(tags or [])
         
     | 
| 
       702 
720 
     | 
    
         
             
                    self.order = order
         
     | 
| 
       703 
721 
     | 
    
         
             
                    variables = {
         
     | 
| 
       704 
722 
     | 
    
         
             
                        "project": self.project,
         
     | 
| 
         @@ -736,7 +754,7 @@ class Artifacts(SizedPaginator["Artifact"]): 
     | 
|
| 
       736 
754 
     | 
    
         
             
                    ):
         
     | 
| 
       737 
755 
     | 
    
         
             
                        raise ValueError(f"Unable to parse {nameof(type(self))!r} response data")
         
     | 
| 
       738 
756 
     | 
    
         | 
| 
       739 
     | 
    
         
            -
                    self.last_response =  
     | 
| 
      
 757 
     | 
    
         
            +
                    self.last_response = _ArtifactConnection.model_validate(conn)
         
     | 
| 
       740 
758 
     | 
    
         | 
| 
       741 
759 
     | 
    
         
             
                @property
         
     | 
| 
       742 
760 
     | 
    
         
             
                def _length(self) -> int:
         
     | 
| 
         @@ -754,9 +772,7 @@ class Artifacts(SizedPaginator["Artifact"]): 
     | 
|
| 
       754 
772 
     | 
    
         | 
| 
       755 
773 
     | 
    
         
             
                    <!-- lazydoc-ignore: internal -->
         
     | 
| 
       756 
774 
     | 
    
         
             
                    """
         
     | 
| 
       757 
     | 
    
         
            -
                     
     | 
| 
       758 
     | 
    
         
            -
                        return True
         
     | 
| 
       759 
     | 
    
         
            -
                    return self.last_response.page_info.has_next_page
         
     | 
| 
      
 775 
     | 
    
         
            +
                    return (conn := self.last_response) is None or conn.has_next
         
     | 
| 
       760 
776 
     | 
    
         | 
| 
       761 
777 
     | 
    
         
             
                @property
         
     | 
| 
       762 
778 
     | 
    
         
             
                def cursor(self) -> str | None:
         
     | 
| 
         @@ -764,9 +780,7 @@ class Artifacts(SizedPaginator["Artifact"]): 
     | 
|
| 
       764 
780 
     | 
    
         | 
| 
       765 
781 
     | 
    
         
             
                    <!-- lazydoc-ignore: internal -->
         
     | 
| 
       766 
782 
     | 
    
         
             
                    """
         
     | 
| 
       767 
     | 
    
         
            -
                    if self.last_response  
     | 
| 
       768 
     | 
    
         
            -
                        return None
         
     | 
| 
       769 
     | 
    
         
            -
                    return self.last_response.edges[-1].cursor
         
     | 
| 
      
 783 
     | 
    
         
            +
                    return conn.next_cursor if (conn := self.last_response) else None
         
     | 
| 
       770 
784 
     | 
    
         | 
| 
       771 
785 
     | 
    
         
             
                def convert_objects(self) -> list[Artifact]:
         
     | 
| 
       772 
786 
     | 
    
         
             
                    """Convert the raw response data into a list of wandb.Artifact objects.
         
     | 
| 
         @@ -799,14 +813,13 @@ class RunArtifacts(SizedPaginator["Artifact"]): 
     | 
|
| 
       799 
813 
     | 
    
         
             
                <!-- lazydoc-ignore-init: internal -->
         
     | 
| 
       800 
814 
     | 
    
         
             
                """
         
     | 
| 
       801 
815 
     | 
    
         | 
| 
       802 
     | 
    
         
            -
                last_response:  
     | 
| 
       803 
     | 
    
         
            -
                    RunOutputArtifactConnectionFragment | RunInputArtifactConnectionFragment
         
     | 
| 
       804 
     | 
    
         
            -
                )
         
     | 
| 
      
 816 
     | 
    
         
            +
                last_response: RunArtifactConnection | None
         
     | 
| 
       805 
817 
     | 
    
         | 
| 
       806 
     | 
    
         
            -
                 
     | 
| 
       807 
     | 
    
         
            -
             
     | 
| 
       808 
     | 
    
         
            -
                     
     | 
| 
       809 
     | 
    
         
            -
                 
     | 
| 
      
 818 
     | 
    
         
            +
                _mode2gqlstr: ClassVar[dict[Literal["logged", "used"], str]] = {
         
     | 
| 
      
 819 
     | 
    
         
            +
                    "logged": RUN_OUTPUT_ARTIFACTS_GQL,
         
     | 
| 
      
 820 
     | 
    
         
            +
                    "used": RUN_INPUT_ARTIFACTS_GQL,
         
     | 
| 
      
 821 
     | 
    
         
            +
                }
         
     | 
| 
      
 822 
     | 
    
         
            +
                """Maps the mode ("logged" or "used") to the corresponding GraphQL query string."""
         
     | 
| 
       810 
823 
     | 
    
         | 
| 
       811 
824 
     | 
    
         
             
                def __init__(
         
     | 
| 
       812 
825 
     | 
    
         
             
                    self,
         
     | 
| 
         @@ -817,20 +830,12 @@ class RunArtifacts(SizedPaginator["Artifact"]): 
     | 
|
| 
       817 
830 
     | 
    
         
             
                ):
         
     | 
| 
       818 
831 
     | 
    
         
             
                    self.run = run
         
     | 
| 
       819 
832 
     | 
    
         | 
| 
       820 
     | 
    
         
            -
                     
     | 
| 
       821 
     | 
    
         
            -
                         
     | 
| 
       822 
     | 
    
         
            -
             
     | 
| 
       823 
     | 
    
         
            -
                            RUN_OUTPUT_ARTIFACTS_GQL, omit_fields=omit_artifact_fields(client)
         
     | 
| 
       824 
     | 
    
         
            -
                        )
         
     | 
| 
       825 
     | 
    
         
            -
                        self._response_cls = RunOutputArtifactConnectionFragment
         
     | 
| 
       826 
     | 
    
         
            -
                    elif mode == "used":
         
     | 
| 
       827 
     | 
    
         
            -
                        self.run_key = "inputArtifacts"
         
     | 
| 
       828 
     | 
    
         
            -
                        self.QUERY = gql_compat(
         
     | 
| 
       829 
     | 
    
         
            -
                            RUN_INPUT_ARTIFACTS_GQL, omit_fields=omit_artifact_fields(client)
         
     | 
| 
       830 
     | 
    
         
            -
                        )
         
     | 
| 
       831 
     | 
    
         
            -
                        self._response_cls = RunInputArtifactConnectionFragment
         
     | 
| 
       832 
     | 
    
         
            -
                    else:
         
     | 
| 
      
 833 
     | 
    
         
            +
                    try:
         
     | 
| 
      
 834 
     | 
    
         
            +
                        query_str = self._mode2gqlstr[mode]
         
     | 
| 
      
 835 
     | 
    
         
            +
                    except LookupError:
         
     | 
| 
       833 
836 
     | 
    
         
             
                        raise ValueError("mode must be logged or used")
         
     | 
| 
      
 837 
     | 
    
         
            +
                    else:
         
     | 
| 
      
 838 
     | 
    
         
            +
                        self.QUERY = gql_compat(query_str, omit_fields=omit_artifact_fields(client))
         
     | 
| 
       834 
839 
     | 
    
         | 
| 
       835 
840 
     | 
    
         
             
                    variable_values = {
         
     | 
| 
       836 
841 
     | 
    
         
             
                        "entity": run.entity,
         
     | 
| 
         @@ -844,8 +849,8 @@ class RunArtifacts(SizedPaginator["Artifact"]): 
     | 
|
| 
       844 
849 
     | 
    
         
             
                    data = self.client.execute(self.QUERY, variable_values=self.variables)
         
     | 
| 
       845 
850 
     | 
    
         | 
| 
       846 
851 
     | 
    
         
             
                    # Extract the inner `*Connection` result for faster/easier access.
         
     | 
| 
       847 
     | 
    
         
            -
                    inner_data = data["project"]["run"][ 
     | 
| 
       848 
     | 
    
         
            -
                    self.last_response =  
     | 
| 
      
 852 
     | 
    
         
            +
                    inner_data = data["project"]["run"]["artifacts"]
         
     | 
| 
      
 853 
     | 
    
         
            +
                    self.last_response = RunArtifactConnection.model_validate(inner_data)
         
     | 
| 
       849 
854 
     | 
    
         | 
| 
       850 
855 
     | 
    
         
             
                @property
         
     | 
| 
       851 
856 
     | 
    
         
             
                def _length(self) -> int:
         
     | 
| 
         @@ -863,9 +868,7 @@ class RunArtifacts(SizedPaginator["Artifact"]): 
     | 
|
| 
       863 
868 
     | 
    
         | 
| 
       864 
869 
     | 
    
         
             
                    <!-- lazydoc-ignore: internal -->
         
     | 
| 
       865 
870 
     | 
    
         
             
                    """
         
     | 
| 
       866 
     | 
    
         
            -
                     
     | 
| 
       867 
     | 
    
         
            -
                        return True
         
     | 
| 
       868 
     | 
    
         
            -
                    return self.last_response.page_info.has_next_page
         
     | 
| 
      
 871 
     | 
    
         
            +
                    return (conn := self.last_response) is None or conn.has_next
         
     | 
| 
       869 
872 
     | 
    
         | 
| 
       870 
873 
     | 
    
         
             
                @property
         
     | 
| 
       871 
874 
     | 
    
         
             
                def cursor(self) -> str | None:
         
     | 
| 
         @@ -873,9 +876,7 @@ class RunArtifacts(SizedPaginator["Artifact"]): 
     | 
|
| 
       873 
876 
     | 
    
         | 
| 
       874 
877 
     | 
    
         
             
                    <!-- lazydoc-ignore: internal -->
         
     | 
| 
       875 
878 
     | 
    
         
             
                    """
         
     | 
| 
       876 
     | 
    
         
            -
                    if self.last_response  
     | 
| 
       877 
     | 
    
         
            -
                        return None
         
     | 
| 
       878 
     | 
    
         
            -
                    return self.last_response.edges[-1].cursor
         
     | 
| 
      
 879 
     | 
    
         
            +
                    return conn.next_cursor if (conn := self.last_response) else None
         
     | 
| 
       879 
880 
     | 
    
         | 
| 
       880 
881 
     | 
    
         
             
                def convert_objects(self) -> list[Artifact]:
         
     | 
| 
       881 
882 
     | 
    
         
             
                    """Convert the raw response data into a list of wandb.Artifact objects.
         
     | 
| 
         @@ -888,16 +889,15 @@ class RunArtifacts(SizedPaginator["Artifact"]): 
     | 
|
| 
       888 
889 
     | 
    
         
             
                    return [
         
     | 
| 
       889 
890 
     | 
    
         
             
                        wandb.Artifact._from_attrs(
         
     | 
| 
       890 
891 
     | 
    
         
             
                            path=FullArtifactPath(
         
     | 
| 
       891 
     | 
    
         
            -
                                prefix=proj. 
     | 
| 
      
 892 
     | 
    
         
            +
                                prefix=proj.entity.name,
         
     | 
| 
       892 
893 
     | 
    
         
             
                                project=proj.name,
         
     | 
| 
       893 
894 
     | 
    
         
             
                                name=f"{artifact_seq.name}:v{node.version_index}",
         
     | 
| 
       894 
895 
     | 
    
         
             
                            ),
         
     | 
| 
       895 
896 
     | 
    
         
             
                            attrs=node,
         
     | 
| 
       896 
897 
     | 
    
         
             
                            client=self.client,
         
     | 
| 
       897 
898 
     | 
    
         
             
                        )
         
     | 
| 
       898 
     | 
    
         
            -
                        for  
     | 
| 
       899 
     | 
    
         
            -
                        if ( 
     | 
| 
       900 
     | 
    
         
            -
                        and (artifact_seq := node.artifact_sequence)
         
     | 
| 
      
 899 
     | 
    
         
            +
                        for node in self.last_response.nodes()
         
     | 
| 
      
 900 
     | 
    
         
            +
                        if (artifact_seq := node.artifact_sequence)
         
     | 
| 
       901 
901 
     | 
    
         
             
                        and (proj := artifact_seq.project)
         
     | 
| 
       902 
902 
     | 
    
         
             
                    ]
         
     | 
| 
       903 
903 
     | 
    
         | 
| 
         @@ -908,7 +908,7 @@ class ArtifactFiles(SizedPaginator["public.File"]): 
     | 
|
| 
       908 
908 
     | 
    
         
             
                <!-- lazydoc-ignore-init: internal -->
         
     | 
| 
       909 
909 
     | 
    
         
             
                """
         
     | 
| 
       910 
910 
     | 
    
         | 
| 
       911 
     | 
    
         
            -
                last_response:  
     | 
| 
      
 911 
     | 
    
         
            +
                last_response: ArtifactFileConnection | None
         
     | 
| 
       912 
912 
     | 
    
         | 
| 
       913 
913 
     | 
    
         
             
                def __init__(
         
     | 
| 
       914 
914 
     | 
    
         
             
                    self,
         
     | 
| 
         @@ -965,7 +965,7 @@ class ArtifactFiles(SizedPaginator["public.File"]): 
     | 
|
| 
       965 
965 
     | 
    
         
             
                    if conn is None:
         
     | 
| 
       966 
966 
     | 
    
         
             
                        raise ValueError(f"Unable to parse {nameof(type(self))!r} response data")
         
     | 
| 
       967 
967 
     | 
    
         | 
| 
       968 
     | 
    
         
            -
                    self.last_response =  
     | 
| 
      
 968 
     | 
    
         
            +
                    self.last_response = ArtifactFileConnection.model_validate(conn)
         
     | 
| 
       969 
969 
     | 
    
         | 
| 
       970 
970 
     | 
    
         
             
                @property
         
     | 
| 
       971 
971 
     | 
    
         
             
                def path(self) -> list[str]:
         
     | 
| 
         @@ -974,12 +974,12 @@ class ArtifactFiles(SizedPaginator["public.File"]): 
     | 
|
| 
       974 
974 
     | 
    
         | 
| 
       975 
975 
     | 
    
         
             
                @property
         
     | 
| 
       976 
976 
     | 
    
         
             
                def _length(self) -> int:
         
     | 
| 
       977 
     | 
    
         
            -
                    if self.last_response is None:
         
     | 
| 
       978 
     | 
    
         
            -
                        self._load_page()
         
     | 
| 
       979 
977 
     | 
    
         
             
                    """Returns the total number of files in the artifact.
         
     | 
| 
       980 
978 
     | 
    
         | 
| 
       981 
979 
     | 
    
         
             
                    <!-- lazydoc-ignore: internal -->
         
     | 
| 
       982 
980 
     | 
    
         
             
                    """
         
     | 
| 
      
 981 
     | 
    
         
            +
                    if self.last_response is None:
         
     | 
| 
      
 982 
     | 
    
         
            +
                        self._load_page()
         
     | 
| 
       983 
983 
     | 
    
         
             
                    return self.artifact.file_count
         
     | 
| 
       984 
984 
     | 
    
         | 
| 
       985 
985 
     | 
    
         
             
                @property
         
     | 
| 
         @@ -988,9 +988,7 @@ class ArtifactFiles(SizedPaginator["public.File"]): 
     | 
|
| 
       988 
988 
     | 
    
         | 
| 
       989 
989 
     | 
    
         
             
                    <!-- lazydoc-ignore: internal -->
         
     | 
| 
       990 
990 
     | 
    
         
             
                    """
         
     | 
| 
       991 
     | 
    
         
            -
                     
     | 
| 
       992 
     | 
    
         
            -
                        return True
         
     | 
| 
       993 
     | 
    
         
            -
                    return self.last_response.page_info.has_next_page
         
     | 
| 
      
 991 
     | 
    
         
            +
                    return (conn := self.last_response) is None or conn.has_next
         
     | 
| 
       994 
992 
     | 
    
         | 
| 
       995 
993 
     | 
    
         
             
                @property
         
     | 
| 
       996 
994 
     | 
    
         
             
                def cursor(self) -> str | None:
         
     | 
| 
         @@ -998,19 +996,10 @@ class ArtifactFiles(SizedPaginator["public.File"]): 
     | 
|
| 
       998 
996 
     | 
    
         | 
| 
       999 
997 
     | 
    
         
             
                    <!-- lazydoc-ignore: internal -->
         
     | 
| 
       1000 
998 
     | 
    
         
             
                    """
         
     | 
| 
       1001 
     | 
    
         
            -
                    if self.last_response  
     | 
| 
       1002 
     | 
    
         
            -
                        return None
         
     | 
| 
       1003 
     | 
    
         
            -
                    return self.last_response.edges[-1].cursor
         
     | 
| 
       1004 
     | 
    
         
            -
             
     | 
| 
       1005 
     | 
    
         
            -
                def update_variables(self) -> None:
         
     | 
| 
       1006 
     | 
    
         
            -
                    """Update the variables dictionary with the cursor.
         
     | 
| 
       1007 
     | 
    
         
            -
             
     | 
| 
       1008 
     | 
    
         
            -
                    <!-- lazydoc-ignore: internal -->
         
     | 
| 
       1009 
     | 
    
         
            -
                    """
         
     | 
| 
       1010 
     | 
    
         
            -
                    self.variables.update({"fileLimit": self.per_page, "fileCursor": self.cursor})
         
     | 
| 
      
 999 
     | 
    
         
            +
                    return conn.next_cursor if (conn := self.last_response) else None
         
     | 
| 
       1011 
1000 
     | 
    
         | 
| 
       1012 
1001 
     | 
    
         
             
                def convert_objects(self) -> list[public.File]:
         
     | 
| 
       1013 
     | 
    
         
            -
                    """Convert the raw response data into a list of  
     | 
| 
      
 1002 
     | 
    
         
            +
                    """Convert the raw response data into a list of File objects.
         
     | 
| 
       1014 
1003 
     | 
    
         | 
| 
       1015 
1004 
     | 
    
         
             
                    <!-- lazydoc-ignore: internal -->
         
     | 
| 
       1016 
1005 
     | 
    
         
             
                    """
         
     |