wandb 0.22.2__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 +2 -2
 - wandb/_pydantic/__init__.py +8 -1
 - wandb/_pydantic/base.py +54 -18
 - wandb/_pydantic/field_types.py +8 -3
 - wandb/_pydantic/pagination.py +46 -0
 - wandb/_pydantic/utils.py +2 -2
 - wandb/apis/public/api.py +24 -19
 - wandb/apis/public/artifacts.py +259 -270
 - wandb/apis/public/registries/_utils.py +40 -54
 - wandb/apis/public/registries/registries_search.py +70 -85
 - wandb/apis/public/registries/registry.py +173 -156
 - wandb/apis/public/runs.py +27 -6
 - wandb/apis/public/utils.py +43 -20
 - wandb/automations/_generated/create_automation.py +2 -2
 - wandb/automations/_generated/create_generic_webhook_integration.py +4 -4
 - wandb/automations/_generated/delete_automation.py +2 -2
 - wandb/automations/_generated/fragments.py +31 -52
 - wandb/automations/_generated/generic_webhook_integrations_by_entity.py +3 -3
 - wandb/automations/_generated/get_automations.py +3 -3
 - wandb/automations/_generated/get_automations_by_entity.py +3 -3
 - wandb/automations/_generated/input_types.py +9 -9
 - wandb/automations/_generated/integrations_by_entity.py +3 -3
 - wandb/automations/_generated/operations.py +6 -6
 - wandb/automations/_generated/slack_integrations_by_entity.py +3 -3
 - wandb/automations/_generated/update_automation.py +2 -2
 - wandb/automations/_utils.py +3 -3
 - wandb/automations/actions.py +3 -3
 - wandb/automations/automations.py +6 -5
 - wandb/bin/gpu_stats.exe +0 -0
 - wandb/bin/wandb-core +0 -0
 - wandb/cli/beta.py +8 -2
 - wandb/cli/beta_leet.py +2 -1
 - wandb/cli/beta_sync.py +1 -1
 - wandb/errors/term.py +8 -8
 - wandb/jupyter.py +0 -51
 - wandb/old/settings.py +6 -6
 - wandb/proto/v3/wandb_internal_pb2.py +351 -352
 - wandb/proto/v3/wandb_server_pb2.py +38 -37
 - wandb/proto/v3/wandb_settings_pb2.py +2 -2
 - wandb/proto/v3/wandb_sync_pb2.py +19 -6
 - wandb/proto/v4/wandb_internal_pb2.py +351 -352
 - wandb/proto/v4/wandb_server_pb2.py +38 -37
 - wandb/proto/v4/wandb_settings_pb2.py +2 -2
 - wandb/proto/v4/wandb_sync_pb2.py +10 -6
 - wandb/proto/v5/wandb_internal_pb2.py +351 -352
 - wandb/proto/v5/wandb_server_pb2.py +38 -37
 - wandb/proto/v5/wandb_settings_pb2.py +2 -2
 - wandb/proto/v5/wandb_sync_pb2.py +10 -6
 - wandb/proto/v6/wandb_internal_pb2.py +351 -352
 - wandb/proto/v6/wandb_server_pb2.py +38 -37
 - wandb/proto/v6/wandb_settings_pb2.py +2 -2
 - wandb/proto/v6/wandb_sync_pb2.py +10 -6
 - wandb/sdk/artifacts/_generated/__init__.py +96 -40
 - wandb/sdk/artifacts/_generated/add_aliases.py +3 -3
 - wandb/sdk/artifacts/_generated/add_artifact_collection_tags.py +26 -0
 - wandb/sdk/artifacts/_generated/artifact_by_id.py +2 -2
 - wandb/sdk/artifacts/_generated/artifact_by_name.py +3 -3
 - wandb/sdk/artifacts/_generated/artifact_collection_membership_file_urls.py +27 -8
 - wandb/sdk/artifacts/_generated/artifact_collection_membership_files.py +27 -8
 - wandb/sdk/artifacts/_generated/artifact_created_by.py +7 -20
 - wandb/sdk/artifacts/_generated/artifact_file_urls.py +19 -6
 - wandb/sdk/artifacts/_generated/artifact_membership_by_name.py +26 -0
 - wandb/sdk/artifacts/_generated/artifact_type.py +5 -5
 - wandb/sdk/artifacts/_generated/artifact_used_by.py +8 -17
 - wandb/sdk/artifacts/_generated/artifact_version_files.py +19 -8
 - wandb/sdk/artifacts/_generated/delete_aliases.py +3 -3
 - wandb/sdk/artifacts/_generated/delete_artifact.py +4 -4
 - wandb/sdk/artifacts/_generated/delete_artifact_collection_tags.py +23 -0
 - wandb/sdk/artifacts/_generated/delete_artifact_portfolio.py +4 -4
 - wandb/sdk/artifacts/_generated/delete_artifact_sequence.py +4 -4
 - wandb/sdk/artifacts/_generated/delete_registry.py +21 -0
 - wandb/sdk/artifacts/_generated/fetch_artifact_manifest.py +8 -20
 - wandb/sdk/artifacts/_generated/fetch_linked_artifacts.py +13 -35
 - wandb/sdk/artifacts/_generated/fetch_org_info_from_entity.py +28 -0
 - wandb/sdk/artifacts/_generated/fetch_registries.py +18 -8
 - wandb/sdk/{projects → artifacts}/_generated/fetch_registry.py +4 -4
 - wandb/sdk/artifacts/_generated/fragments.py +183 -333
 - wandb/sdk/artifacts/_generated/input_types.py +133 -7
 - wandb/sdk/artifacts/_generated/link_artifact.py +5 -5
 - wandb/sdk/artifacts/_generated/operations.py +1053 -548
 - wandb/sdk/artifacts/_generated/project_artifact_collection.py +9 -77
 - wandb/sdk/artifacts/_generated/project_artifact_collections.py +21 -9
 - wandb/sdk/artifacts/_generated/project_artifact_type.py +3 -3
 - wandb/sdk/artifacts/_generated/project_artifact_types.py +19 -6
 - wandb/sdk/artifacts/_generated/project_artifacts.py +7 -8
 - wandb/sdk/artifacts/_generated/registry_collections.py +21 -9
 - wandb/sdk/artifacts/_generated/registry_versions.py +20 -9
 - wandb/sdk/artifacts/_generated/rename_registry.py +25 -0
 - wandb/sdk/artifacts/_generated/run_input_artifacts.py +5 -9
 - wandb/sdk/artifacts/_generated/run_output_artifacts.py +5 -9
 - wandb/sdk/artifacts/_generated/type_info.py +2 -2
 - wandb/sdk/artifacts/_generated/unlink_artifact.py +3 -5
 - wandb/sdk/artifacts/_generated/update_artifact.py +3 -3
 - wandb/sdk/artifacts/_generated/update_artifact_collection_type.py +28 -0
 - wandb/sdk/artifacts/_generated/update_artifact_portfolio.py +7 -16
 - wandb/sdk/artifacts/_generated/update_artifact_sequence.py +7 -16
 - wandb/sdk/artifacts/_generated/upsert_registry.py +25 -0
 - wandb/sdk/artifacts/_gqlutils.py +170 -6
 - wandb/sdk/artifacts/_models/__init__.py +9 -0
 - wandb/sdk/artifacts/_models/artifact_collection.py +109 -0
 - wandb/sdk/artifacts/_models/manifest.py +26 -0
 - wandb/sdk/artifacts/_models/pagination.py +26 -0
 - wandb/sdk/artifacts/_models/registry.py +100 -0
 - wandb/sdk/artifacts/_validators.py +45 -27
 - wandb/sdk/artifacts/artifact.py +220 -215
 - wandb/sdk/artifacts/artifact_file_cache.py +1 -1
 - wandb/sdk/artifacts/artifact_manifest.py +37 -32
 - wandb/sdk/artifacts/artifact_manifest_entry.py +80 -125
 - wandb/sdk/artifacts/artifact_manifests/artifact_manifest_v1.py +43 -61
 - wandb/sdk/artifacts/storage_handlers/gcs_handler.py +8 -6
 - wandb/sdk/data_types/image.py +2 -2
 - wandb/sdk/interface/interface.py +72 -64
 - wandb/sdk/interface/interface_queue.py +27 -18
 - wandb/sdk/interface/interface_shared.py +61 -23
 - wandb/sdk/interface/interface_sock.py +9 -5
 - wandb/sdk/internal/_generated/server_features_query.py +4 -4
 - wandb/sdk/launch/inputs/schema.py +13 -10
 - wandb/sdk/lib/apikey.py +8 -12
 - wandb/sdk/lib/asyncio_compat.py +1 -1
 - wandb/sdk/lib/asyncio_manager.py +5 -5
 - wandb/sdk/lib/console_capture.py +38 -30
 - wandb/sdk/lib/progress.py +159 -64
 - wandb/sdk/lib/retry.py +3 -2
 - wandb/sdk/lib/service/service_connection.py +2 -2
 - wandb/sdk/lib/wb_logging.py +2 -1
 - wandb/sdk/mailbox/mailbox.py +1 -1
 - wandb/sdk/wandb_init.py +10 -13
 - wandb/sdk/wandb_run.py +9 -46
 - wandb/sdk/wandb_settings.py +102 -19
 - {wandb-0.22.2.dist-info → wandb-0.22.3.dist-info}/METADATA +2 -1
 - {wandb-0.22.2.dist-info → wandb-0.22.3.dist-info}/RECORD +135 -134
 - wandb/sdk/artifacts/_generated/artifact_via_membership_by_name.py +0 -26
 - wandb/sdk/artifacts/_generated/create_artifact_collection_tag_assignments.py +0 -36
 - wandb/sdk/artifacts/_generated/delete_artifact_collection_tag_assignments.py +0 -25
 - wandb/sdk/artifacts/_generated/move_artifact_collection.py +0 -35
 - wandb/sdk/projects/_generated/__init__.py +0 -26
 - wandb/sdk/projects/_generated/delete_project.py +0 -22
 - wandb/sdk/projects/_generated/enums.py +0 -4
 - wandb/sdk/projects/_generated/fragments.py +0 -41
 - wandb/sdk/projects/_generated/input_types.py +0 -13
 - wandb/sdk/projects/_generated/operations.py +0 -88
 - wandb/sdk/projects/_generated/rename_project.py +0 -27
 - wandb/sdk/projects/_generated/upsert_registry_project.py +0 -27
 - {wandb-0.22.2.dist-info → wandb-0.22.3.dist-info}/WHEEL +0 -0
 - {wandb-0.22.2.dist-info → wandb-0.22.3.dist-info}/entry_points.txt +0 -0
 - {wandb-0.22.2.dist-info → wandb-0.22.3.dist-info}/licenses/LICENSE +0 -0
 
| 
         @@ -2,29 +2,34 @@ from __future__ import annotations 
     | 
|
| 
       2 
2 
     | 
    
         | 
| 
       3 
3 
     | 
    
         
             
            from typing import TYPE_CHECKING, Any, Literal
         
     | 
| 
       4 
4 
     | 
    
         | 
| 
      
 5 
     | 
    
         
            +
            from pydantic import PositiveInt
         
     | 
| 
       5 
6 
     | 
    
         
             
            from wandb_gql import gql
         
     | 
| 
       6 
7 
     | 
    
         | 
| 
       7 
8 
     | 
    
         
             
            import wandb
         
     | 
| 
       8 
9 
     | 
    
         
             
            from wandb._analytics import tracked
         
     | 
| 
       9 
     | 
    
         
            -
            from wandb.proto 
     | 
| 
       10 
     | 
    
         
            -
            from wandb.sdk.artifacts. 
     | 
| 
       11 
     | 
    
         
            -
             
     | 
| 
       12 
     | 
    
         
            -
            from wandb.sdk.projects._generated import (
         
     | 
| 
       13 
     | 
    
         
            -
                DELETE_PROJECT_GQL,
         
     | 
| 
      
 10 
     | 
    
         
            +
            from wandb.proto import wandb_internal_pb2 as pb
         
     | 
| 
      
 11 
     | 
    
         
            +
            from wandb.sdk.artifacts._generated import (
         
     | 
| 
      
 12 
     | 
    
         
            +
                DELETE_REGISTRY_GQL,
         
     | 
| 
       14 
13 
     | 
    
         
             
                FETCH_REGISTRY_GQL,
         
     | 
| 
       15 
     | 
    
         
            -
                 
     | 
| 
       16 
     | 
    
         
            -
                 
     | 
| 
       17 
     | 
    
         
            -
                 
     | 
| 
       18 
     | 
    
         
            -
                 
     | 
| 
       19 
     | 
    
         
            -
                 
     | 
| 
      
 14 
     | 
    
         
            +
                RENAME_REGISTRY_GQL,
         
     | 
| 
      
 15 
     | 
    
         
            +
                UPSERT_REGISTRY_GQL,
         
     | 
| 
      
 16 
     | 
    
         
            +
                DeleteRegistry,
         
     | 
| 
      
 17 
     | 
    
         
            +
                FetchRegistry,
         
     | 
| 
      
 18 
     | 
    
         
            +
                RegistryFragment,
         
     | 
| 
      
 19 
     | 
    
         
            +
                RenameProjectInput,
         
     | 
| 
      
 20 
     | 
    
         
            +
                RenameRegistry,
         
     | 
| 
      
 21 
     | 
    
         
            +
                UpsertModelInput,
         
     | 
| 
      
 22 
     | 
    
         
            +
                UpsertRegistry,
         
     | 
| 
       20 
23 
     | 
    
         
             
            )
         
     | 
| 
      
 24 
     | 
    
         
            +
            from wandb.sdk.artifacts._gqlutils import server_supports
         
     | 
| 
      
 25 
     | 
    
         
            +
            from wandb.sdk.artifacts._models import RegistryData
         
     | 
| 
      
 26 
     | 
    
         
            +
            from wandb.sdk.artifacts._validators import REGISTRY_PREFIX, validate_project_name
         
     | 
| 
       21 
27 
     | 
    
         | 
| 
       22 
28 
     | 
    
         
             
            from ._freezable_list import AddOnlyArtifactTypesList
         
     | 
| 
       23 
29 
     | 
    
         
             
            from ._utils import (
         
     | 
| 
      
 30 
     | 
    
         
            +
                Visibility,
         
     | 
| 
       24 
31 
     | 
    
         
             
                fetch_org_entity_from_organization,
         
     | 
| 
       25 
     | 
    
         
            -
                 
     | 
| 
       26 
     | 
    
         
            -
                gql_to_registry_visibility,
         
     | 
| 
       27 
     | 
    
         
            -
                registry_visibility_to_gql,
         
     | 
| 
      
 32 
     | 
    
         
            +
                prepare_artifact_types_input,
         
     | 
| 
       28 
33 
     | 
    
         
             
            )
         
     | 
| 
       29 
34 
     | 
    
         
             
            from .registries_search import Collections, Versions
         
     | 
| 
       30 
35 
     | 
    
         | 
| 
         @@ -35,86 +40,86 @@ if TYPE_CHECKING: 
     | 
|
| 
       35 
40 
     | 
    
         
             
            class Registry:
         
     | 
| 
       36 
41 
     | 
    
         
             
                """A single registry in the Registry."""
         
     | 
| 
       37 
42 
     | 
    
         | 
| 
      
 43 
     | 
    
         
            +
                _saved: RegistryData
         
     | 
| 
      
 44 
     | 
    
         
            +
                """The saved registry data as last fetched from the W&B server."""
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
                _current: RegistryData
         
     | 
| 
      
 47 
     | 
    
         
            +
                """The local, editable registry data."""
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
       38 
49 
     | 
    
         
             
                def __init__(
         
     | 
| 
       39 
50 
     | 
    
         
             
                    self,
         
     | 
| 
       40 
51 
     | 
    
         
             
                    client: Client,
         
     | 
| 
       41 
52 
     | 
    
         
             
                    organization: str,
         
     | 
| 
       42 
53 
     | 
    
         
             
                    entity: str,
         
     | 
| 
       43 
54 
     | 
    
         
             
                    name: str,
         
     | 
| 
       44 
     | 
    
         
            -
                    attrs:  
     | 
| 
      
 55 
     | 
    
         
            +
                    attrs: RegistryFragment | None = None,
         
     | 
| 
       45 
56 
     | 
    
         
             
                ):
         
     | 
| 
       46 
57 
     | 
    
         
             
                    self.client = client
         
     | 
| 
       47 
     | 
    
         
            -
                    self._name = name
         
     | 
| 
       48 
     | 
    
         
            -
                    self._saved_name = name
         
     | 
| 
       49 
     | 
    
         
            -
                    self._entity = entity
         
     | 
| 
       50 
     | 
    
         
            -
                    self._organization = organization
         
     | 
| 
       51 
     | 
    
         
            -
                    if attrs is not None:
         
     | 
| 
       52 
     | 
    
         
            -
                        self._update_attributes(attrs)
         
     | 
| 
       53 
58 
     | 
    
         | 
| 
       54 
     | 
    
         
            -
             
     | 
| 
       55 
     | 
    
         
            -
             
     | 
| 
       56 
     | 
    
         
            -
             
     | 
| 
       57 
     | 
    
         
            -
             
     | 
| 
       58 
     | 
    
         
            -
             
     | 
| 
      
 59 
     | 
    
         
            +
                    if attrs is None:
         
     | 
| 
      
 60 
     | 
    
         
            +
                        # FIXME: This is awkward and bypasses validation which seems shaky.
         
     | 
| 
      
 61 
     | 
    
         
            +
                        # Reconsider the init signature of `Registry` so this isn't necessary?
         
     | 
| 
      
 62 
     | 
    
         
            +
                        draft = RegistryData.model_construct(
         
     | 
| 
      
 63 
     | 
    
         
            +
                            organization=organization, entity=entity, name=name
         
     | 
| 
      
 64 
     | 
    
         
            +
                        )
         
     | 
| 
      
 65 
     | 
    
         
            +
                        self._saved = draft
         
     | 
| 
      
 66 
     | 
    
         
            +
                        self._current = draft.model_copy(deep=True)
         
     | 
| 
      
 67 
     | 
    
         
            +
                    else:
         
     | 
| 
      
 68 
     | 
    
         
            +
                        self._update_attributes(attrs)
         
     | 
| 
       59 
69 
     | 
    
         | 
| 
       60 
     | 
    
         
            -
             
     | 
| 
       61 
     | 
    
         
            -
                     
     | 
| 
       62 
     | 
    
         
            -
             
     | 
| 
       63 
     | 
    
         
            -
                     
     | 
| 
       64 
     | 
    
         
            -
                    self. 
     | 
| 
       65 
     | 
    
         
            -
                        t["node"]["name"] for t in attrs.get("artifactTypes", {}).get("edges", [])
         
     | 
| 
       66 
     | 
    
         
            -
                    )
         
     | 
| 
       67 
     | 
    
         
            -
                    self._created_at = attrs.get("createdAt", "")
         
     | 
| 
       68 
     | 
    
         
            -
                    self._updated_at = attrs.get("updatedAt", "")
         
     | 
| 
       69 
     | 
    
         
            -
                    self._visibility = gql_to_registry_visibility(attrs.get("access", ""))
         
     | 
| 
      
 70 
     | 
    
         
            +
                def _update_attributes(self, fragment: RegistryFragment) -> None:
         
     | 
| 
      
 71 
     | 
    
         
            +
                    """Internal helper method to update instance attributes from GraphQL fragment data."""
         
     | 
| 
      
 72 
     | 
    
         
            +
                    saved = RegistryData.from_fragment(fragment)
         
     | 
| 
      
 73 
     | 
    
         
            +
                    self._saved = saved
         
     | 
| 
      
 74 
     | 
    
         
            +
                    self._current = saved.model_copy(deep=True)
         
     | 
| 
       70 
75 
     | 
    
         | 
| 
       71 
76 
     | 
    
         
             
                @property
         
     | 
| 
       72 
77 
     | 
    
         
             
                def full_name(self) -> str:
         
     | 
| 
       73 
78 
     | 
    
         
             
                    """Full name of the registry including the `wandb-registry-` prefix."""
         
     | 
| 
       74 
     | 
    
         
            -
                    return  
     | 
| 
      
 79 
     | 
    
         
            +
                    return self._current.full_name
         
     | 
| 
       75 
80 
     | 
    
         | 
| 
       76 
81 
     | 
    
         
             
                @property
         
     | 
| 
       77 
82 
     | 
    
         
             
                def name(self) -> str:
         
     | 
| 
       78 
83 
     | 
    
         
             
                    """Name of the registry without the `wandb-registry-` prefix."""
         
     | 
| 
       79 
     | 
    
         
            -
                    return self. 
     | 
| 
      
 84 
     | 
    
         
            +
                    return self._current.name
         
     | 
| 
       80 
85 
     | 
    
         | 
| 
       81 
86 
     | 
    
         
             
                @name.setter
         
     | 
| 
       82 
87 
     | 
    
         
             
                def name(self, value: str):
         
     | 
| 
       83 
     | 
    
         
            -
                    self. 
     | 
| 
      
 88 
     | 
    
         
            +
                    self._current.name = value
         
     | 
| 
       84 
89 
     | 
    
         | 
| 
       85 
90 
     | 
    
         
             
                @property
         
     | 
| 
       86 
91 
     | 
    
         
             
                def entity(self) -> str:
         
     | 
| 
       87 
92 
     | 
    
         
             
                    """Organization entity of the registry."""
         
     | 
| 
       88 
     | 
    
         
            -
                    return self. 
     | 
| 
      
 93 
     | 
    
         
            +
                    return self._current.entity
         
     | 
| 
       89 
94 
     | 
    
         | 
| 
       90 
95 
     | 
    
         
             
                @property
         
     | 
| 
       91 
96 
     | 
    
         
             
                def organization(self) -> str:
         
     | 
| 
       92 
97 
     | 
    
         
             
                    """Organization name of the registry."""
         
     | 
| 
       93 
     | 
    
         
            -
                    return self. 
     | 
| 
      
 98 
     | 
    
         
            +
                    return self._current.organization
         
     | 
| 
       94 
99 
     | 
    
         | 
| 
       95 
100 
     | 
    
         
             
                @property
         
     | 
| 
       96 
101 
     | 
    
         
             
                def description(self) -> str:
         
     | 
| 
       97 
102 
     | 
    
         
             
                    """Description of the registry."""
         
     | 
| 
       98 
     | 
    
         
            -
                    return self. 
     | 
| 
      
 103 
     | 
    
         
            +
                    return self._current.description
         
     | 
| 
       99 
104 
     | 
    
         | 
| 
       100 
105 
     | 
    
         
             
                @description.setter
         
     | 
| 
       101 
106 
     | 
    
         
             
                def description(self, value: str):
         
     | 
| 
       102 
107 
     | 
    
         
             
                    """Set the description of the registry."""
         
     | 
| 
       103 
     | 
    
         
            -
                    self. 
     | 
| 
      
 108 
     | 
    
         
            +
                    self._current.description = value
         
     | 
| 
       104 
109 
     | 
    
         | 
| 
       105 
110 
     | 
    
         
             
                @property
         
     | 
| 
       106 
     | 
    
         
            -
                def allow_all_artifact_types(self):
         
     | 
| 
      
 111 
     | 
    
         
            +
                def allow_all_artifact_types(self) -> bool:
         
     | 
| 
       107 
112 
     | 
    
         
             
                    """Returns whether all artifact types are allowed in the registry.
         
     | 
| 
       108 
113 
     | 
    
         | 
| 
       109 
114 
     | 
    
         
             
                    If `True` then artifacts of any type can be added to this registry.
         
     | 
| 
       110 
115 
     | 
    
         
             
                    If `False` then artifacts are restricted to the types in `artifact_types` for this registry.
         
     | 
| 
       111 
116 
     | 
    
         
             
                    """
         
     | 
| 
       112 
     | 
    
         
            -
                    return self. 
     | 
| 
      
 117 
     | 
    
         
            +
                    return self._current.allow_all_artifact_types
         
     | 
| 
       113 
118 
     | 
    
         | 
| 
       114 
119 
     | 
    
         
             
                @allow_all_artifact_types.setter
         
     | 
| 
       115 
     | 
    
         
            -
                def allow_all_artifact_types(self, value: bool):
         
     | 
| 
      
 120 
     | 
    
         
            +
                def allow_all_artifact_types(self, value: bool) -> None:
         
     | 
| 
       116 
121 
     | 
    
         
             
                    """Set whether all artifact types are allowed in the registry."""
         
     | 
| 
       117 
     | 
    
         
            -
                    self. 
     | 
| 
      
 122 
     | 
    
         
            +
                    self._current.allow_all_artifact_types = value
         
     | 
| 
       118 
123 
     | 
    
         | 
| 
       119 
124 
     | 
    
         
             
                @property
         
     | 
| 
       120 
125 
     | 
    
         
             
                def artifact_types(self) -> AddOnlyArtifactTypesList:
         
     | 
| 
         @@ -141,20 +146,20 @@ class Registry: 
     | 
|
| 
       141 
146 
     | 
    
         
             
                    )  # Types can only be removed if it has not been saved yet
         
     | 
| 
       142 
147 
     | 
    
         
             
                    ```
         
     | 
| 
       143 
148 
     | 
    
         
             
                    """
         
     | 
| 
       144 
     | 
    
         
            -
                    return self. 
     | 
| 
      
 149 
     | 
    
         
            +
                    return self._current.artifact_types
         
     | 
| 
       145 
150 
     | 
    
         | 
| 
       146 
151 
     | 
    
         
             
                @property
         
     | 
| 
       147 
152 
     | 
    
         
             
                def created_at(self) -> str:
         
     | 
| 
       148 
153 
     | 
    
         
             
                    """Timestamp of when the registry was created."""
         
     | 
| 
       149 
     | 
    
         
            -
                    return self. 
     | 
| 
      
 154 
     | 
    
         
            +
                    return self._current.created_at
         
     | 
| 
       150 
155 
     | 
    
         | 
| 
       151 
156 
     | 
    
         
             
                @property
         
     | 
| 
       152 
157 
     | 
    
         
             
                def updated_at(self) -> str:
         
     | 
| 
       153 
158 
     | 
    
         
             
                    """Timestamp of when the registry was last updated."""
         
     | 
| 
       154 
     | 
    
         
            -
                    return self. 
     | 
| 
      
 159 
     | 
    
         
            +
                    return self._current.updated_at
         
     | 
| 
       155 
160 
     | 
    
         | 
| 
       156 
161 
     | 
    
         
             
                @property
         
     | 
| 
       157 
     | 
    
         
            -
                def path(self):
         
     | 
| 
      
 162 
     | 
    
         
            +
                def path(self) -> list[str]:
         
     | 
| 
       158 
163 
     | 
    
         
             
                    return [self.entity, self.full_name]
         
     | 
| 
       159 
164 
     | 
    
         | 
| 
       160 
165 
     | 
    
         
             
                @property
         
     | 
| 
         @@ -168,7 +173,7 @@ class Registry: 
     | 
|
| 
       168 
173 
     | 
    
         
             
                            - "restricted": Only invited members via the UI can access this registry.
         
     | 
| 
       169 
174 
     | 
    
         
             
                              Public sharing is disabled.
         
     | 
| 
       170 
175 
     | 
    
         
             
                    """
         
     | 
| 
       171 
     | 
    
         
            -
                    return self. 
     | 
| 
      
 176 
     | 
    
         
            +
                    return self._current.visibility.name
         
     | 
| 
       172 
177 
     | 
    
         | 
| 
       173 
178 
     | 
    
         
             
                @visibility.setter
         
     | 
| 
       174 
179 
     | 
    
         
             
                def visibility(self, value: Literal["organization", "restricted"]):
         
     | 
| 
         @@ -181,23 +186,34 @@ class Registry: 
     | 
|
| 
       181 
186 
     | 
    
         
             
                            - "restricted": Only invited members via the UI can access this registry.
         
     | 
| 
       182 
187 
     | 
    
         
             
                              Public sharing is disabled.
         
     | 
| 
       183 
188 
     | 
    
         
             
                    """
         
     | 
| 
       184 
     | 
    
         
            -
                    self. 
     | 
| 
      
 189 
     | 
    
         
            +
                    self._current.visibility = value
         
     | 
| 
       185 
190 
     | 
    
         | 
| 
       186 
191 
     | 
    
         
             
                @tracked
         
     | 
| 
       187 
     | 
    
         
            -
                def collections( 
     | 
| 
      
 192 
     | 
    
         
            +
                def collections(
         
     | 
| 
      
 193 
     | 
    
         
            +
                    self, filter: dict[str, Any] | None = None, per_page: PositiveInt = 100
         
     | 
| 
      
 194 
     | 
    
         
            +
                ) -> Collections:
         
     | 
| 
       188 
195 
     | 
    
         
             
                    """Returns the collections belonging to the registry."""
         
     | 
| 
       189 
     | 
    
         
            -
                     
     | 
| 
       190 
     | 
    
         
            -
                         
     | 
| 
       191 
     | 
    
         
            -
             
     | 
| 
       192 
     | 
    
         
            -
             
     | 
| 
      
 196 
     | 
    
         
            +
                    return Collections(
         
     | 
| 
      
 197 
     | 
    
         
            +
                        client=self.client,
         
     | 
| 
      
 198 
     | 
    
         
            +
                        organization=self.organization,
         
     | 
| 
      
 199 
     | 
    
         
            +
                        registry_filter={"name": self.full_name},
         
     | 
| 
      
 200 
     | 
    
         
            +
                        collection_filter=filter,
         
     | 
| 
      
 201 
     | 
    
         
            +
                        per_page=per_page,
         
     | 
| 
      
 202 
     | 
    
         
            +
                    )
         
     | 
| 
       193 
203 
     | 
    
         | 
| 
       194 
204 
     | 
    
         
             
                @tracked
         
     | 
| 
       195 
     | 
    
         
            -
                def versions( 
     | 
| 
      
 205 
     | 
    
         
            +
                def versions(
         
     | 
| 
      
 206 
     | 
    
         
            +
                    self, filter: dict[str, Any] | None = None, per_page: PositiveInt = 100
         
     | 
| 
      
 207 
     | 
    
         
            +
                ) -> Versions:
         
     | 
| 
       196 
208 
     | 
    
         
             
                    """Returns the versions belonging to the registry."""
         
     | 
| 
       197 
     | 
    
         
            -
                     
     | 
| 
       198 
     | 
    
         
            -
                         
     | 
| 
       199 
     | 
    
         
            -
             
     | 
| 
       200 
     | 
    
         
            -
             
     | 
| 
      
 209 
     | 
    
         
            +
                    return Versions(
         
     | 
| 
      
 210 
     | 
    
         
            +
                        client=self.client,
         
     | 
| 
      
 211 
     | 
    
         
            +
                        organization=self.organization,
         
     | 
| 
      
 212 
     | 
    
         
            +
                        registry_filter={"name": self.full_name},
         
     | 
| 
      
 213 
     | 
    
         
            +
                        collection_filter=None,
         
     | 
| 
      
 214 
     | 
    
         
            +
                        artifact_filter=filter,
         
     | 
| 
      
 215 
     | 
    
         
            +
                        per_page=per_page,
         
     | 
| 
      
 216 
     | 
    
         
            +
                    )
         
     | 
| 
       201 
217 
     | 
    
         | 
| 
       202 
218 
     | 
    
         
             
                @classmethod
         
     | 
| 
       203 
219 
     | 
    
         
             
                @tracked
         
     | 
| 
         @@ -230,141 +246,142 @@ class Registry: 
     | 
|
| 
       230 
246 
     | 
    
         
             
                        ValueError: If a registry with the same name already exists in the
         
     | 
| 
       231 
247 
     | 
    
         
             
                            organization or if the creation fails.
         
     | 
| 
       232 
248 
     | 
    
         
             
                    """
         
     | 
| 
       233 
     | 
    
         
            -
                     
     | 
| 
       234 
     | 
    
         
            -
                    full_name = REGISTRY_PREFIX + name
         
     | 
| 
       235 
     | 
    
         
            -
                    validate_project_name(full_name)
         
     | 
| 
       236 
     | 
    
         
            -
                    accepted_artifact_types = []
         
     | 
| 
       237 
     | 
    
         
            -
                    if artifact_types:
         
     | 
| 
       238 
     | 
    
         
            -
                        accepted_artifact_types = format_gql_artifact_types_input(artifact_types)
         
     | 
| 
       239 
     | 
    
         
            -
                    visibility_value = registry_visibility_to_gql(visibility)
         
     | 
| 
       240 
     | 
    
         
            -
                    registry_creation_error = (
         
     | 
| 
      
 249 
     | 
    
         
            +
                    failed_msg = (
         
     | 
| 
       241 
250 
     | 
    
         
             
                        f"Failed to create registry {name!r} in organization {organization!r}."
         
     | 
| 
       242 
251 
     | 
    
         
             
                    )
         
     | 
| 
      
 252 
     | 
    
         
            +
             
     | 
| 
      
 253 
     | 
    
         
            +
                    org_entity = fetch_org_entity_from_organization(client, organization)
         
     | 
| 
      
 254 
     | 
    
         
            +
             
     | 
| 
      
 255 
     | 
    
         
            +
                    gql_op = gql(UPSERT_REGISTRY_GQL)
         
     | 
| 
      
 256 
     | 
    
         
            +
                    gql_input = UpsertModelInput(
         
     | 
| 
      
 257 
     | 
    
         
            +
                        description=description,
         
     | 
| 
      
 258 
     | 
    
         
            +
                        entity_name=org_entity,
         
     | 
| 
      
 259 
     | 
    
         
            +
                        name=validate_project_name(f"{REGISTRY_PREFIX}{name}"),
         
     | 
| 
      
 260 
     | 
    
         
            +
                        access=Visibility.from_python(visibility).value,
         
     | 
| 
      
 261 
     | 
    
         
            +
                        allow_all_artifact_types_in_registry=not artifact_types,
         
     | 
| 
      
 262 
     | 
    
         
            +
                        artifact_types=prepare_artifact_types_input(artifact_types),
         
     | 
| 
      
 263 
     | 
    
         
            +
                    )
         
     | 
| 
      
 264 
     | 
    
         
            +
                    gql_vars = {"input": gql_input.model_dump()}
         
     | 
| 
       243 
265 
     | 
    
         
             
                    try:
         
     | 
| 
       244 
     | 
    
         
            -
                         
     | 
| 
       245 
     | 
    
         
            -
             
     | 
| 
       246 
     | 
    
         
            -
             
     | 
| 
       247 
     | 
    
         
            -
             
     | 
| 
       248 
     | 
    
         
            -
             
     | 
| 
       249 
     | 
    
         
            -
             
     | 
| 
       250 
     | 
    
         
            -
                                "access": visibility_value,
         
     | 
| 
       251 
     | 
    
         
            -
                                "allowAllArtifactTypesInRegistry": not accepted_artifact_types,
         
     | 
| 
       252 
     | 
    
         
            -
                                "artifactTypes": accepted_artifact_types,
         
     | 
| 
       253 
     | 
    
         
            -
                            },
         
     | 
| 
       254 
     | 
    
         
            -
                        )
         
     | 
| 
       255 
     | 
    
         
            -
                    except Exception:
         
     | 
| 
       256 
     | 
    
         
            -
                        raise ValueError(registry_creation_error)
         
     | 
| 
       257 
     | 
    
         
            -
                    if not response["upsertModel"]["inserted"]:
         
     | 
| 
       258 
     | 
    
         
            -
                        raise ValueError(registry_creation_error)
         
     | 
| 
      
 266 
     | 
    
         
            +
                        data = client.execute(gql_op, variable_values=gql_vars)
         
     | 
| 
      
 267 
     | 
    
         
            +
                        result = UpsertRegistry.model_validate(data).upsert_model
         
     | 
| 
      
 268 
     | 
    
         
            +
                    except Exception as e:
         
     | 
| 
      
 269 
     | 
    
         
            +
                        raise ValueError(failed_msg) from e
         
     | 
| 
      
 270 
     | 
    
         
            +
                    if not (result and result.inserted and (registry_project := result.project)):
         
     | 
| 
      
 271 
     | 
    
         
            +
                        raise ValueError(failed_msg)
         
     | 
| 
       259 
272 
     | 
    
         | 
| 
       260 
273 
     | 
    
         
             
                    return Registry(
         
     | 
| 
       261 
274 
     | 
    
         
             
                        client,
         
     | 
| 
       262 
     | 
    
         
            -
                        organization,
         
     | 
| 
       263 
     | 
    
         
            -
                        org_entity,
         
     | 
| 
       264 
     | 
    
         
            -
                        name,
         
     | 
| 
       265 
     | 
    
         
            -
                         
     | 
| 
      
 275 
     | 
    
         
            +
                        organization=organization,
         
     | 
| 
      
 276 
     | 
    
         
            +
                        entity=org_entity,
         
     | 
| 
      
 277 
     | 
    
         
            +
                        name=name,
         
     | 
| 
      
 278 
     | 
    
         
            +
                        attrs=registry_project,
         
     | 
| 
       266 
279 
     | 
    
         
             
                    )
         
     | 
| 
       267 
280 
     | 
    
         | 
| 
       268 
281 
     | 
    
         
             
                @tracked
         
     | 
| 
       269 
282 
     | 
    
         
             
                def delete(self) -> None:
         
     | 
| 
       270 
283 
     | 
    
         
             
                    """Delete the registry. This is irreversible."""
         
     | 
| 
      
 284 
     | 
    
         
            +
                    failed_msg = f"Failed to delete registry {self.name!r} in organization {self.organization!r}"
         
     | 
| 
      
 285 
     | 
    
         
            +
             
     | 
| 
      
 286 
     | 
    
         
            +
                    gql_op = gql(DELETE_REGISTRY_GQL)
         
     | 
| 
      
 287 
     | 
    
         
            +
                    gql_vars = {"id": self._saved.id}
         
     | 
| 
       271 
288 
     | 
    
         
             
                    try:
         
     | 
| 
       272 
     | 
    
         
            -
                         
     | 
| 
       273 
     | 
    
         
            -
             
     | 
| 
       274 
     | 
    
         
            -
             
     | 
| 
       275 
     | 
    
         
            -
                         
     | 
| 
       276 
     | 
    
         
            -
                     
     | 
| 
       277 
     | 
    
         
            -
                        raise ValueError(
         
     | 
| 
       278 
     | 
    
         
            -
                            f"Failed to delete registry: {self.name!r} in organization: {self.organization!r}"
         
     | 
| 
       279 
     | 
    
         
            -
                        )
         
     | 
| 
       280 
     | 
    
         
            -
                    if not result.delete_model.success:
         
     | 
| 
       281 
     | 
    
         
            -
                        raise ValueError(
         
     | 
| 
       282 
     | 
    
         
            -
                            f"Failed to delete registry: {self.name!r} in organization: {self.organization!r}"
         
     | 
| 
       283 
     | 
    
         
            -
                        )
         
     | 
| 
      
 289 
     | 
    
         
            +
                        data = self.client.execute(gql_op, variable_values=gql_vars)
         
     | 
| 
      
 290 
     | 
    
         
            +
                        result = DeleteRegistry.model_validate(data).delete_model
         
     | 
| 
      
 291 
     | 
    
         
            +
                    except Exception as e:
         
     | 
| 
      
 292 
     | 
    
         
            +
                        raise ValueError(failed_msg) from e
         
     | 
| 
      
 293 
     | 
    
         
            +
                    if not (result and result.success):
         
     | 
| 
      
 294 
     | 
    
         
            +
                        raise ValueError(failed_msg)
         
     | 
| 
       284 
295 
     | 
    
         | 
| 
       285 
296 
     | 
    
         
             
                @tracked
         
     | 
| 
       286 
297 
     | 
    
         
             
                def load(self) -> None:
         
     | 
| 
       287 
298 
     | 
    
         
             
                    """Load the registry attributes from the backend to reflect the latest saved state."""
         
     | 
| 
       288 
     | 
    
         
            -
                     
     | 
| 
       289 
     | 
    
         
            -
             
     | 
| 
       290 
     | 
    
         
            -
             
     | 
| 
       291 
     | 
    
         
            -
                     
     | 
| 
      
 299 
     | 
    
         
            +
                    failed_msg = f"Failed to load registry {self.name!r} in organization {self.organization!r}."
         
     | 
| 
      
 300 
     | 
    
         
            +
             
     | 
| 
      
 301 
     | 
    
         
            +
                    gql_op = gql(FETCH_REGISTRY_GQL)
         
     | 
| 
      
 302 
     | 
    
         
            +
                    gql_vars = {"name": self.full_name, "entity": self.entity}
         
     | 
| 
       292 
303 
     | 
    
         
             
                    try:
         
     | 
| 
       293 
     | 
    
         
            -
                         
     | 
| 
       294 
     | 
    
         
            -
             
     | 
| 
       295 
     | 
    
         
            -
             
     | 
| 
       296 
     | 
    
         
            -
             
     | 
| 
       297 
     | 
    
         
            -
             
     | 
| 
       298 
     | 
    
         
            -
             
     | 
| 
       299 
     | 
    
         
            -
                        )
         
     | 
| 
       300 
     | 
    
         
            -
             
     | 
| 
       301 
     | 
    
         
            -
             
     | 
| 
       302 
     | 
    
         
            -
                    if response["entity"] is None:
         
     | 
| 
       303 
     | 
    
         
            -
                        raise ValueError(load_failure_message)
         
     | 
| 
       304 
     | 
    
         
            -
                    self.attrs = response["entity"]["project"]
         
     | 
| 
       305 
     | 
    
         
            -
                    if self.attrs is None:
         
     | 
| 
       306 
     | 
    
         
            -
                        raise ValueError(load_failure_message)
         
     | 
| 
       307 
     | 
    
         
            -
                    self._update_attributes(self.attrs)
         
     | 
| 
      
 304 
     | 
    
         
            +
                        data = self.client.execute(gql_op, variable_values=gql_vars)
         
     | 
| 
      
 305 
     | 
    
         
            +
                        result = FetchRegistry.model_validate(data)
         
     | 
| 
      
 306 
     | 
    
         
            +
                    except Exception as e:
         
     | 
| 
      
 307 
     | 
    
         
            +
                        raise ValueError(failed_msg) from e
         
     | 
| 
      
 308 
     | 
    
         
            +
             
     | 
| 
      
 309 
     | 
    
         
            +
                    if not ((entity := result.entity) and (registry_project := entity.project)):
         
     | 
| 
      
 310 
     | 
    
         
            +
                        raise ValueError(failed_msg)
         
     | 
| 
      
 311 
     | 
    
         
            +
             
     | 
| 
      
 312 
     | 
    
         
            +
                    self._update_attributes(registry_project)
         
     | 
| 
       308 
313 
     | 
    
         | 
| 
       309 
314 
     | 
    
         
             
                @tracked
         
     | 
| 
       310 
315 
     | 
    
         
             
                def save(self) -> None:
         
     | 
| 
       311 
316 
     | 
    
         
             
                    """Save registry attributes to the backend."""
         
     | 
| 
       312 
     | 
    
         
            -
                    if not  
     | 
| 
       313 
     | 
    
         
            -
                         
     | 
| 
      
 317 
     | 
    
         
            +
                    if not server_supports(
         
     | 
| 
      
 318 
     | 
    
         
            +
                        self.client, pb.INCLUDE_ARTIFACT_TYPES_IN_REGISTRY_CREATION
         
     | 
| 
       314 
319 
     | 
    
         
             
                    ):
         
     | 
| 
       315 
320 
     | 
    
         
             
                        raise RuntimeError(
         
     | 
| 
       316 
     | 
    
         
            -
                            " 
     | 
| 
      
 321 
     | 
    
         
            +
                            "Saving the registry is not enabled on this wandb server version. "
         
     | 
| 
       317 
322 
     | 
    
         
             
                            "Please upgrade your server version or contact support at support@wandb.com."
         
     | 
| 
       318 
323 
     | 
    
         
             
                        )
         
     | 
| 
       319 
324 
     | 
    
         | 
| 
       320 
     | 
    
         
            -
                     
     | 
| 
      
 325 
     | 
    
         
            +
                    # If `artifact_types.draft` has items, it means the user has added artifact types that aren't saved yet.
         
     | 
| 
      
 326 
     | 
    
         
            +
                    if (
         
     | 
| 
      
 327 
     | 
    
         
            +
                        new_artifact_types := self.artifact_types.draft
         
     | 
| 
      
 328 
     | 
    
         
            +
                    ) and self.allow_all_artifact_types:
         
     | 
| 
       321 
329 
     | 
    
         
             
                        raise ValueError(
         
     | 
| 
       322 
330 
     | 
    
         
             
                            f"Cannot update artifact types when `allows_all_artifact_types` is {True!r}. Set it to {False!r} first."
         
     | 
| 
       323 
331 
     | 
    
         
             
                        )
         
     | 
| 
       324 
332 
     | 
    
         | 
| 
       325 
     | 
    
         
            -
                     
     | 
| 
       326 
     | 
    
         
            -
             
     | 
| 
       327 
     | 
    
         
            -
                     
     | 
| 
       328 
     | 
    
         
            -
                     
     | 
| 
       329 
     | 
    
         
            -
             
     | 
| 
      
 333 
     | 
    
         
            +
                    failed_msg = f"Failed to save registry {self.name!r} in organization {self.organization!r}"
         
     | 
| 
      
 334 
     | 
    
         
            +
             
     | 
| 
      
 335 
     | 
    
         
            +
                    old_project_name = validate_project_name(self._saved.full_name)
         
     | 
| 
      
 336 
     | 
    
         
            +
                    new_project_name = validate_project_name(self._current.full_name)
         
     | 
| 
      
 337 
     | 
    
         
            +
             
     | 
| 
      
 338 
     | 
    
         
            +
                    upsert_op = gql(UPSERT_REGISTRY_GQL)
         
     | 
| 
      
 339 
     | 
    
         
            +
                    upsert_input = UpsertModelInput(
         
     | 
| 
      
 340 
     | 
    
         
            +
                        description=self.description,
         
     | 
| 
      
 341 
     | 
    
         
            +
                        entity_name=self.entity,
         
     | 
| 
      
 342 
     | 
    
         
            +
                        name=old_project_name,
         
     | 
| 
      
 343 
     | 
    
         
            +
                        access=self._current.visibility.value,
         
     | 
| 
      
 344 
     | 
    
         
            +
                        allow_all_artifact_types_in_registry=self.allow_all_artifact_types,
         
     | 
| 
      
 345 
     | 
    
         
            +
                        artifact_types=prepare_artifact_types_input(new_artifact_types),
         
     | 
| 
      
 346 
     | 
    
         
            +
                    )
         
     | 
| 
      
 347 
     | 
    
         
            +
                    upsert_vars = {"input": upsert_input.model_dump()}
         
     | 
| 
       330 
348 
     | 
    
         
             
                    try:
         
     | 
| 
       331 
     | 
    
         
            -
                         
     | 
| 
       332 
     | 
    
         
            -
             
     | 
| 
       333 
     | 
    
         
            -
             
     | 
| 
       334 
     | 
    
         
            -
             
     | 
| 
       335 
     | 
    
         
            -
             
     | 
| 
       336 
     | 
    
         
            -
             
     | 
| 
       337 
     | 
    
         
            -
                                "access": visibility_value,
         
     | 
| 
       338 
     | 
    
         
            -
                                "allowAllArtifactTypesInRegistry": self.allow_all_artifact_types,
         
     | 
| 
       339 
     | 
    
         
            -
                                "artifactTypes": newly_added_types,
         
     | 
| 
       340 
     | 
    
         
            -
                            },
         
     | 
| 
       341 
     | 
    
         
            -
                        )
         
     | 
| 
       342 
     | 
    
         
            -
                        result = UpsertRegistryProject.model_validate(response)
         
     | 
| 
       343 
     | 
    
         
            -
                    except Exception:
         
     | 
| 
       344 
     | 
    
         
            -
                        raise ValueError(registry_save_error)
         
     | 
| 
       345 
     | 
    
         
            -
                    if result.upsert_model.inserted:
         
     | 
| 
      
 349 
     | 
    
         
            +
                        data = self.client.execute(upsert_op, variable_values=upsert_vars)
         
     | 
| 
      
 350 
     | 
    
         
            +
                        result = UpsertRegistry.model_validate(data).upsert_model
         
     | 
| 
      
 351 
     | 
    
         
            +
                    except Exception as e:
         
     | 
| 
      
 352 
     | 
    
         
            +
                        raise ValueError(failed_msg) from e
         
     | 
| 
      
 353 
     | 
    
         
            +
             
     | 
| 
      
 354 
     | 
    
         
            +
                    if result and result.inserted:
         
     | 
| 
       346 
355 
     | 
    
         
             
                        # This is not suppose trigger unless the user has messed with the `_saved_name` variable
         
     | 
| 
       347 
356 
     | 
    
         
             
                        wandb.termlog(
         
     | 
| 
       348 
357 
     | 
    
         
             
                            f"Created registry {self.name!r} in organization {self.organization!r} on save"
         
     | 
| 
       349 
358 
     | 
    
         
             
                        )
         
     | 
| 
       350 
     | 
    
         
            -
             
     | 
| 
      
 359 
     | 
    
         
            +
             
     | 
| 
      
 360 
     | 
    
         
            +
                    if not (result and (registry_project := result.project)):
         
     | 
| 
      
 361 
     | 
    
         
            +
                        raise ValueError(failed_msg)
         
     | 
| 
      
 362 
     | 
    
         
            +
             
     | 
| 
      
 363 
     | 
    
         
            +
                    self._update_attributes(registry_project)
         
     | 
| 
       351 
364 
     | 
    
         | 
| 
       352 
365 
     | 
    
         
             
                    # Update the name of the registry if it has changed
         
     | 
| 
       353 
     | 
    
         
            -
                    if  
     | 
| 
       354 
     | 
    
         
            -
                         
     | 
| 
       355 
     | 
    
         
            -
             
     | 
| 
       356 
     | 
    
         
            -
                             
     | 
| 
       357 
     | 
    
         
            -
             
     | 
| 
       358 
     | 
    
         
            -
             
     | 
| 
       359 
     | 
    
         
            -
                                "newProjectName": self.full_name,
         
     | 
| 
       360 
     | 
    
         
            -
                            },
         
     | 
| 
      
 366 
     | 
    
         
            +
                    if old_project_name != new_project_name:
         
     | 
| 
      
 367 
     | 
    
         
            +
                        rename_op = gql(RENAME_REGISTRY_GQL)
         
     | 
| 
      
 368 
     | 
    
         
            +
                        rename_input = RenameProjectInput(
         
     | 
| 
      
 369 
     | 
    
         
            +
                            entity_name=self.entity,
         
     | 
| 
      
 370 
     | 
    
         
            +
                            old_project_name=old_project_name,
         
     | 
| 
      
 371 
     | 
    
         
            +
                            new_project_name=new_project_name,
         
     | 
| 
       361 
372 
     | 
    
         
             
                        )
         
     | 
| 
       362 
     | 
    
         
            -
                         
     | 
| 
       363 
     | 
    
         
            -
                         
     | 
| 
       364 
     | 
    
         
            -
                         
     | 
| 
      
 373 
     | 
    
         
            +
                        rename_vars = {"input": rename_input.model_dump()}
         
     | 
| 
      
 374 
     | 
    
         
            +
                        data = self.client.execute(rename_op, variable_values=rename_vars)
         
     | 
| 
      
 375 
     | 
    
         
            +
                        result = RenameRegistry.model_validate(data).rename_project
         
     | 
| 
      
 376 
     | 
    
         
            +
                        if not (result and (registry_project := result.project)):
         
     | 
| 
      
 377 
     | 
    
         
            +
                            raise ValueError(failed_msg)
         
     | 
| 
      
 378 
     | 
    
         
            +
             
     | 
| 
      
 379 
     | 
    
         
            +
                        if result.inserted:
         
     | 
| 
       365 
380 
     | 
    
         
             
                            # This is not suppose trigger unless the user has messed with the `_saved_name` variable
         
     | 
| 
       366 
381 
     | 
    
         
             
                            wandb.termlog(f"Created new registry {self.name!r} on save")
         
     | 
| 
       367 
382 
     | 
    
         | 
| 
      
 383 
     | 
    
         
            +
                        self._update_attributes(registry_project)
         
     | 
| 
      
 384 
     | 
    
         
            +
             
     | 
| 
       368 
385 
     | 
    
         
             
                def _no_updating_registry_types(self) -> bool:
         
     | 
| 
       369 
386 
     | 
    
         
             
                    # artifact types draft means user assigned types to add that are not yet saved
         
     | 
| 
       370 
387 
     | 
    
         
             
                    return len(self.artifact_types.draft) > 0 and self.allow_all_artifact_types
         
     | 
    
        wandb/apis/public/runs.py
    CHANGED
    
    | 
         @@ -745,21 +745,24 @@ class Run(Attrs): 
     | 
|
| 
       745 
745 
     | 
    
         
             
                                withRuns=False,
         
     | 
| 
       746 
746 
     | 
    
         
             
                            )
         
     | 
| 
       747 
747 
     | 
    
         | 
| 
       748 
     | 
    
         
            -
                    if not self._is_loaded:
         
     | 
| 
      
 748 
     | 
    
         
            +
                    if not self._is_loaded or force:
         
     | 
| 
       749 
749 
     | 
    
         
             
                        # Always set _project_internal_id if projectId is available, regardless of fragment type
         
     | 
| 
       750 
750 
     | 
    
         
             
                        if "projectId" in self._attrs:
         
     | 
| 
       751 
751 
     | 
    
         
             
                            self._project_internal_id = int(self._attrs["projectId"])
         
     | 
| 
       752 
752 
     | 
    
         
             
                        else:
         
     | 
| 
       753 
753 
     | 
    
         
             
                            self._project_internal_id = None
         
     | 
| 
       754 
754 
     | 
    
         | 
| 
       755 
     | 
    
         
            -
                        #  
     | 
| 
      
 755 
     | 
    
         
            +
                        # Always call _load_from_attrs when using the full fragment or when the fields are actually present
         
     | 
| 
       756 
756 
     | 
    
         
             
                        if fragment_name == RUN_FRAGMENT_NAME or (
         
     | 
| 
       757 
757 
     | 
    
         
             
                            "config" in self._attrs
         
     | 
| 
       758 
758 
     | 
    
         
             
                            or "summaryMetrics" in self._attrs
         
     | 
| 
       759 
759 
     | 
    
         
             
                            or "systemMetrics" in self._attrs
         
     | 
| 
       760 
760 
     | 
    
         
             
                        ):
         
     | 
| 
       761 
761 
     | 
    
         
             
                            self._load_from_attrs()
         
     | 
| 
       762 
     | 
    
         
            -
             
     | 
| 
      
 762 
     | 
    
         
            +
             
     | 
| 
      
 763 
     | 
    
         
            +
                        # Only mark as loaded for lightweight fragments, not full fragments
         
     | 
| 
      
 764 
     | 
    
         
            +
                        if fragment_name == LIGHTWEIGHT_RUN_FRAGMENT_NAME:
         
     | 
| 
      
 765 
     | 
    
         
            +
                            self._is_loaded = True
         
     | 
| 
       763 
766 
     | 
    
         | 
| 
       764 
767 
     | 
    
         
             
                    return self._attrs
         
     | 
| 
       765 
768 
     | 
    
         | 
| 
         @@ -1305,7 +1308,13 @@ class Run(Attrs): 
     | 
|
| 
       1305 
1308 
     | 
    
         
             
                    """Get run config. Auto-loads full data if in lazy mode."""
         
     | 
| 
       1306 
1309 
     | 
    
         
             
                    if self._lazy and not self._full_data_loaded and "config" not in self._attrs:
         
     | 
| 
       1307 
1310 
     | 
    
         
             
                        self.load_full_data()
         
     | 
| 
       1308 
     | 
    
         
            -
             
     | 
| 
      
 1311 
     | 
    
         
            +
             
     | 
| 
      
 1312 
     | 
    
         
            +
                    # Ensure config is always converted to dict (defensive against conversion issues)
         
     | 
| 
      
 1313 
     | 
    
         
            +
                    config_value = self._attrs.get("config", {})
         
     | 
| 
      
 1314 
     | 
    
         
            +
                    # _convert_to_dict handles dict inputs (noop) and converts str/bytes/bytearray to dict
         
     | 
| 
      
 1315 
     | 
    
         
            +
                    config_value = _convert_to_dict(config_value)
         
     | 
| 
      
 1316 
     | 
    
         
            +
                    self._attrs["config"] = config_value
         
     | 
| 
      
 1317 
     | 
    
         
            +
                    return config_value
         
     | 
| 
       1309 
1318 
     | 
    
         | 
| 
       1310 
1319 
     | 
    
         
             
                @property
         
     | 
| 
       1311 
1320 
     | 
    
         
             
                def summary(self):
         
     | 
| 
         @@ -1332,7 +1341,13 @@ class Run(Attrs): 
     | 
|
| 
       1332 
1341 
     | 
    
         
             
                        and "systemMetrics" not in self._attrs
         
     | 
| 
       1333 
1342 
     | 
    
         
             
                    ):
         
     | 
| 
       1334 
1343 
     | 
    
         
             
                        self.load_full_data()
         
     | 
| 
       1335 
     | 
    
         
            -
             
     | 
| 
      
 1344 
     | 
    
         
            +
             
     | 
| 
      
 1345 
     | 
    
         
            +
                    # Ensure systemMetrics is always converted to dict (defensive against conversion issues)
         
     | 
| 
      
 1346 
     | 
    
         
            +
                    system_metrics_value = self._attrs.get("systemMetrics", {})
         
     | 
| 
      
 1347 
     | 
    
         
            +
                    # _convert_to_dict handles dict inputs (noop) and converts str/bytes/bytearray to dict
         
     | 
| 
      
 1348 
     | 
    
         
            +
                    system_metrics_value = _convert_to_dict(system_metrics_value)
         
     | 
| 
      
 1349 
     | 
    
         
            +
                    self._attrs["systemMetrics"] = system_metrics_value
         
     | 
| 
      
 1350 
     | 
    
         
            +
                    return system_metrics_value
         
     | 
| 
       1336 
1351 
     | 
    
         | 
| 
       1337 
1352 
     | 
    
         
             
                @property
         
     | 
| 
       1338 
1353 
     | 
    
         
             
                def summary_metrics(self):
         
     | 
| 
         @@ -1343,7 +1358,13 @@ class Run(Attrs): 
     | 
|
| 
       1343 
1358 
     | 
    
         
             
                        and "summaryMetrics" not in self._attrs
         
     | 
| 
       1344 
1359 
     | 
    
         
             
                    ):
         
     | 
| 
       1345 
1360 
     | 
    
         
             
                        self.load_full_data()
         
     | 
| 
       1346 
     | 
    
         
            -
             
     | 
| 
      
 1361 
     | 
    
         
            +
             
     | 
| 
      
 1362 
     | 
    
         
            +
                    # Ensure summaryMetrics is always converted to dict (defensive against conversion issues)
         
     | 
| 
      
 1363 
     | 
    
         
            +
                    summary_metrics_value = self._attrs.get("summaryMetrics", {})
         
     | 
| 
      
 1364 
     | 
    
         
            +
                    # _convert_to_dict handles dict inputs (noop) and converts str/bytes/bytearray to dict
         
     | 
| 
      
 1365 
     | 
    
         
            +
                    summary_metrics_value = _convert_to_dict(summary_metrics_value)
         
     | 
| 
      
 1366 
     | 
    
         
            +
                    self._attrs["summaryMetrics"] = summary_metrics_value
         
     | 
| 
      
 1367 
     | 
    
         
            +
                    return summary_metrics_value
         
     | 
| 
       1347 
1368 
     | 
    
         | 
| 
       1348 
1369 
     | 
    
         
             
                @property
         
     | 
| 
       1349 
1370 
     | 
    
         
             
                def rawconfig(self):
         
     | 
    
        wandb/apis/public/utils.py
    CHANGED
    
    | 
         @@ -6,7 +6,9 @@ from typing import Any, Iterable, Mapping 
     | 
|
| 
       6 
6 
     | 
    
         
             
            from urllib.parse import urlparse
         
     | 
| 
       7 
7 
     | 
    
         | 
| 
       8 
8 
     | 
    
         
             
            from wandb_gql import gql
         
     | 
| 
      
 9 
     | 
    
         
            +
            from wandb_graphql import TypeInfo
         
     | 
| 
       9 
10 
     | 
    
         
             
            from wandb_graphql.language import ast, visitor
         
     | 
| 
      
 11 
     | 
    
         
            +
            from wandb_graphql.validation.validation import ValidationContext
         
     | 
| 
       10 
12 
     | 
    
         | 
| 
       11 
13 
     | 
    
         
             
            from wandb._iterutils import one
         
     | 
| 
       12 
14 
     | 
    
         
             
            from wandb.sdk.artifacts._validators import is_artifact_registry_project
         
     | 
| 
         @@ -112,11 +114,6 @@ def fetch_org_from_settings_or_entity( 
     | 
|
| 
       112 
114 
     | 
    
         
             
            class _GQLCompatRewriter(visitor.Visitor):
         
     | 
| 
       113 
115 
     | 
    
         
             
                """GraphQL AST visitor to rewrite queries/mutations to be compatible with older server versions."""
         
     | 
| 
       114 
116 
     | 
    
         | 
| 
       115 
     | 
    
         
            -
                omit_variables: set[str]
         
     | 
| 
       116 
     | 
    
         
            -
                omit_fragments: set[str]
         
     | 
| 
       117 
     | 
    
         
            -
                omit_fields: set[str]
         
     | 
| 
       118 
     | 
    
         
            -
                rename_fields: dict[str, str]
         
     | 
| 
       119 
     | 
    
         
            -
             
     | 
| 
       120 
117 
     | 
    
         
             
                def __init__(
         
     | 
| 
       121 
118 
     | 
    
         
             
                    self,
         
     | 
| 
       122 
119 
     | 
    
         
             
                    omit_variables: Iterable[str] | None = None,
         
     | 
| 
         @@ -129,25 +126,52 @@ class _GQLCompatRewriter(visitor.Visitor): 
     | 
|
| 
       129 
126 
     | 
    
         
             
                    self.omit_fields = set(omit_fields or ())
         
     | 
| 
       130 
127 
     | 
    
         
             
                    self.rename_fields = dict(rename_fields or {})
         
     | 
| 
       131 
128 
     | 
    
         | 
| 
       132 
     | 
    
         
            -
                def  
     | 
| 
       133 
     | 
    
         
            -
                     
     | 
| 
      
 129 
     | 
    
         
            +
                def leave_Document(self, node: ast.Document, *_, **__) -> Any:  # noqa: N802
         
     | 
| 
      
 130 
     | 
    
         
            +
                    # After rewriting the GQL document, prune "orphan" (unused) fragment definitions.
         
     | 
| 
      
 131 
     | 
    
         
            +
                    # Note: The ValidationContext doesn't require a schema here, as we only use it to check for reachable fragments.
         
     | 
| 
      
 132 
     | 
    
         
            +
                    ctx = ValidationContext(schema=None, ast=node, type_info=TypeInfo(schema=None))
         
     | 
| 
      
 133 
     | 
    
         
            +
                    operation_defns = {
         
     | 
| 
      
 134 
     | 
    
         
            +
                        dfn for dfn in node.definitions if isinstance(dfn, ast.OperationDefinition)
         
     | 
| 
      
 135 
     | 
    
         
            +
                    }
         
     | 
| 
      
 136 
     | 
    
         
            +
                    used_fragment_defns = {
         
     | 
| 
      
 137 
     | 
    
         
            +
                        frag
         
     | 
| 
      
 138 
     | 
    
         
            +
                        for op in operation_defns
         
     | 
| 
      
 139 
     | 
    
         
            +
                        for frag in ctx.get_recursively_referenced_fragments(op)
         
     | 
| 
      
 140 
     | 
    
         
            +
                    }
         
     | 
| 
      
 141 
     | 
    
         
            +
                    # Preserve original defintion order
         
     | 
| 
      
 142 
     | 
    
         
            +
                    allowed_defns = operation_defns | used_fragment_defns
         
     | 
| 
      
 143 
     | 
    
         
            +
                    node.definitions = [dfn for dfn in node.definitions if (dfn in allowed_defns)]
         
     | 
| 
      
 144 
     | 
    
         
            +
             
     | 
| 
      
 145 
     | 
    
         
            +
                def enter_Variable(self, node: ast.Variable, *_, **__) -> Any:  # noqa: N802
         
     | 
| 
      
 146 
     | 
    
         
            +
                    if node.name.value in self.omit_variables:
         
     | 
| 
       134 
147 
     | 
    
         
             
                        return visitor.REMOVE
         
     | 
| 
       135 
148 
     | 
    
         | 
| 
       136 
     | 
    
         
            -
                def  
     | 
| 
       137 
     | 
    
         
            -
                    # For context,  
     | 
| 
      
 149 
     | 
    
         
            +
                def leave_VariableDefinition(self, node: ast.VariableDefinition, *_, **__) -> Any:  # noqa: N802
         
     | 
| 
      
 150 
     | 
    
         
            +
                    # For context, consider the `$varName: String` variable definition below:
         
     | 
| 
      
 151 
     | 
    
         
            +
                    #   (..., $varName: String, ...)
         
     | 
| 
      
 152 
     | 
    
         
            +
                    #
         
     | 
| 
      
 153 
     | 
    
         
            +
                    # On ENTERING, the AST looks like:
         
     | 
| 
      
 154 
     | 
    
         
            +
                    #     VariableDefinition(variable=Variable(name=Name(value='varName')), ...)
         
     | 
| 
       138 
155 
     | 
    
         
             
                    #
         
     | 
| 
       139 
     | 
    
         
            -
                    # 
     | 
| 
       140 
     | 
    
         
            -
                    # 
     | 
| 
      
 156 
     | 
    
         
            +
                    # On LEAVING, if `$varName` was removed, the AST looks like:
         
     | 
| 
      
 157 
     | 
    
         
            +
                    #     VariableDefinition(variable=REMOVE, ...)
         
     | 
| 
      
 158 
     | 
    
         
            +
                    if node.variable is visitor.REMOVE:
         
     | 
| 
      
 159 
     | 
    
         
            +
                        return visitor.REMOVE
         
     | 
| 
      
 160 
     | 
    
         
            +
             
     | 
| 
      
 161 
     | 
    
         
            +
                def leave_ObjectField(self, node: ast.ObjectField, *_, **__) -> Any:  # noqa: N802
         
     | 
| 
      
 162 
     | 
    
         
            +
                    # For context, consider `argName: $varName` in the input args below:
         
     | 
| 
      
 163 
     | 
    
         
            +
                    #   input: {..., argName: $varName, ...}
         
     | 
| 
       141 
164 
     | 
    
         
             
                    #
         
     | 
| 
       142 
     | 
    
         
            -
                    #  
     | 
| 
      
 165 
     | 
    
         
            +
                    # On ENTERING, the AST for `argName: $varName` looks like:
         
     | 
| 
      
 166 
     | 
    
         
            +
                    #     ObjectField(
         
     | 
| 
      
 167 
     | 
    
         
            +
                    #       name=Name(value='argName'), value=Variable(name=Name(value='varName')),
         
     | 
| 
      
 168 
     | 
    
         
            +
                    #     )
         
     | 
| 
       143 
169 
     | 
    
         
             
                    #
         
     | 
| 
       144 
     | 
    
         
            -
                    # 
     | 
| 
       145 
     | 
    
         
            -
                    #     ObjectField( 
     | 
| 
       146 
     | 
    
         
            -
                    # 
     | 
| 
       147 
     | 
    
         
            -
                     
     | 
| 
       148 
     | 
    
         
            -
             
     | 
| 
       149 
     | 
    
         
            -
                        and var.name.value in self.omit_variables
         
     | 
| 
       150 
     | 
    
         
            -
                    ):
         
     | 
| 
      
 170 
     | 
    
         
            +
                    # On LEAVING, if `$varName` was removed, the AST looks like:
         
     | 
| 
      
 171 
     | 
    
         
            +
                    #     ObjectField(
         
     | 
| 
      
 172 
     | 
    
         
            +
                    #       name=Name(value='argName'), value=REMOVE,
         
     | 
| 
      
 173 
     | 
    
         
            +
                    #     )
         
     | 
| 
      
 174 
     | 
    
         
            +
                    if node.value is visitor.REMOVE:
         
     | 
| 
       151 
175 
     | 
    
         
             
                        return visitor.REMOVE
         
     | 
| 
       152 
176 
     | 
    
         | 
| 
       153 
177 
     | 
    
         
             
                def enter_Argument(self, node: ast.Argument, *_, **__) -> Any:  # noqa: N802
         
     | 
| 
         @@ -167,7 +191,6 @@ class _GQLCompatRewriter(visitor.Visitor): 
     | 
|
| 
       167 
191 
     | 
    
         
             
                        return visitor.REMOVE
         
     | 
| 
       168 
192 
     | 
    
         
             
                    if new_name := self.rename_fields.get(node.name.value):
         
     | 
| 
       169 
193 
     | 
    
         
             
                        node.name.value = new_name
         
     | 
| 
       170 
     | 
    
         
            -
                        return node
         
     | 
| 
       171 
194 
     | 
    
         | 
| 
       172 
195 
     | 
    
         
             
                def leave_Field(self, node: ast.Field, *_, **__) -> Any:  # noqa: N802
         
     | 
| 
       173 
196 
     | 
    
         
             
                    # If the field had a selection set, but now it's empty, remove the field entirely
         
     | 
| 
         @@ -5,12 +5,12 @@ from __future__ import annotations 
     | 
|
| 
       5 
5 
     | 
    
         | 
| 
       6 
6 
     | 
    
         
             
            from typing import Optional
         
     | 
| 
       7 
7 
     | 
    
         | 
| 
       8 
     | 
    
         
            -
            from wandb._pydantic import  
     | 
| 
      
 8 
     | 
    
         
            +
            from wandb._pydantic import GQLResult
         
     | 
| 
       9 
9 
     | 
    
         | 
| 
       10 
10 
     | 
    
         
             
            from .fragments import CreateAutomationResult
         
     | 
| 
       11 
11 
     | 
    
         | 
| 
       12 
12 
     | 
    
         | 
| 
       13 
     | 
    
         
            -
            class CreateAutomation( 
     | 
| 
      
 13 
     | 
    
         
            +
            class CreateAutomation(GQLResult):
         
     | 
| 
       14 
14 
     | 
    
         
             
                result: Optional[CreateAutomationResult]
         
     | 
| 
       15 
15 
     | 
    
         | 
| 
       16 
16 
     | 
    
         |