wandb 0.19.6__py3-none-macosx_11_0_arm64.whl → 0.19.7__py3-none-macosx_11_0_arm64.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 +25 -5
- wandb/apis/public/_generated/__init__.py +21 -0
- wandb/apis/public/_generated/base.py +128 -0
- wandb/apis/public/_generated/enums.py +4 -0
- wandb/apis/public/_generated/input_types.py +4 -0
- wandb/apis/public/_generated/operations.py +15 -0
- wandb/apis/public/_generated/server_features_query.py +27 -0
- wandb/apis/public/_generated/typing_compat.py +14 -0
- wandb/apis/public/api.py +192 -6
- wandb/apis/public/artifacts.py +13 -45
- wandb/apis/public/registries.py +573 -0
- wandb/apis/public/utils.py +36 -0
- wandb/bin/gpu_stats +0 -0
- wandb/bin/wandb-core +0 -0
- wandb/cli/cli.py +11 -20
- wandb/env.py +10 -0
- wandb/proto/v3/wandb_internal_pb2.py +243 -222
- wandb/proto/v3/wandb_server_pb2.py +4 -4
- wandb/proto/v3/wandb_settings_pb2.py +1 -1
- wandb/proto/v4/wandb_internal_pb2.py +226 -222
- wandb/proto/v4/wandb_server_pb2.py +4 -4
- wandb/proto/v4/wandb_settings_pb2.py +1 -1
- wandb/proto/v5/wandb_internal_pb2.py +226 -222
- wandb/proto/v5/wandb_server_pb2.py +4 -4
- wandb/proto/v5/wandb_settings_pb2.py +1 -1
- wandb/sdk/artifacts/_graphql_fragments.py +126 -0
- wandb/sdk/artifacts/artifact.py +43 -88
- wandb/sdk/backend/backend.py +1 -1
- wandb/sdk/data_types/helper_types/bounding_boxes_2d.py +14 -6
- wandb/sdk/data_types/helper_types/image_mask.py +12 -6
- wandb/sdk/data_types/saved_model.py +35 -46
- wandb/sdk/data_types/video.py +7 -16
- wandb/sdk/interface/interface.py +26 -10
- wandb/sdk/interface/interface_queue.py +5 -8
- wandb/sdk/interface/interface_relay.py +1 -6
- wandb/sdk/interface/interface_shared.py +21 -99
- wandb/sdk/interface/interface_sock.py +2 -13
- wandb/sdk/interface/router.py +21 -15
- wandb/sdk/interface/router_queue.py +2 -1
- wandb/sdk/interface/router_relay.py +2 -1
- wandb/sdk/interface/router_sock.py +5 -4
- wandb/sdk/internal/handler.py +4 -3
- wandb/sdk/internal/internal_api.py +12 -1
- wandb/sdk/internal/sender.py +0 -18
- wandb/sdk/lib/apikey.py +87 -26
- wandb/sdk/lib/asyncio_compat.py +210 -0
- wandb/sdk/lib/progress.py +78 -16
- wandb/sdk/lib/service_connection.py +1 -1
- wandb/sdk/lib/sock_client.py +7 -7
- wandb/sdk/mailbox/__init__.py +23 -0
- wandb/sdk/mailbox/handles.py +199 -0
- wandb/sdk/mailbox/mailbox.py +121 -0
- wandb/sdk/mailbox/wait_with_progress.py +134 -0
- wandb/sdk/service/server_sock.py +5 -1
- wandb/sdk/service/streams.py +66 -74
- wandb/sdk/verify/verify.py +54 -2
- wandb/sdk/wandb_init.py +61 -61
- wandb/sdk/wandb_login.py +7 -4
- wandb/sdk/wandb_metadata.py +65 -34
- wandb/sdk/wandb_require.py +14 -8
- wandb/sdk/wandb_run.py +82 -87
- wandb/sdk/wandb_settings.py +3 -3
- wandb/sdk/wandb_setup.py +19 -8
- wandb/sdk/wandb_sync.py +2 -4
- wandb/util.py +3 -1
- {wandb-0.19.6.dist-info → wandb-0.19.7.dist-info}/METADATA +2 -2
- {wandb-0.19.6.dist-info → wandb-0.19.7.dist-info}/RECORD +71 -58
- wandb/sdk/lib/mailbox.py +0 -442
- {wandb-0.19.6.dist-info → wandb-0.19.7.dist-info}/WHEEL +0 -0
- {wandb-0.19.6.dist-info → wandb-0.19.7.dist-info}/entry_points.txt +0 -0
- {wandb-0.19.6.dist-info → wandb-0.19.7.dist-info}/licenses/LICENSE +0 -0
    
        wandb/__init__.py
    CHANGED
    
    
    
        wandb/__init__.pyi
    CHANGED
    
    | @@ -63,6 +63,7 @@ from typing import ( | |
| 63 63 | 
             
                Any,
         | 
| 64 64 | 
             
                Callable,
         | 
| 65 65 | 
             
                Dict,
         | 
| 66 | 
            +
                Iterable,
         | 
| 66 67 | 
             
                List,
         | 
| 67 68 | 
             
                Literal,
         | 
| 68 69 | 
             
                Optional,
         | 
| @@ -103,7 +104,7 @@ if TYPE_CHECKING: | |
| 103 104 | 
             
                import wandb
         | 
| 104 105 | 
             
                from wandb.plot import CustomChart
         | 
| 105 106 |  | 
| 106 | 
            -
            __version__: str = "0.19. | 
| 107 | 
            +
            __version__: str = "0.19.7"
         | 
| 107 108 |  | 
| 108 109 | 
             
            run: Run | None
         | 
| 109 110 | 
             
            config: wandb_config.Config
         | 
| @@ -114,6 +115,25 @@ _sentry: Sentry | |
| 114 115 | 
             
            api: InternalApi
         | 
| 115 116 | 
             
            patched: Dict[str, List[Callable]]
         | 
| 116 117 |  | 
| 118 | 
            +
            def require(
         | 
| 119 | 
            +
                requirement: str | Iterable[str] | None = None,
         | 
| 120 | 
            +
                experiment: str | Iterable[str] | None = None,
         | 
| 121 | 
            +
            ) -> None:
         | 
| 122 | 
            +
                """Indicate which experimental features are used by the script.
         | 
| 123 | 
            +
             | 
| 124 | 
            +
                This should be called before any other `wandb` functions, ideally right
         | 
| 125 | 
            +
                after importing `wandb`.
         | 
| 126 | 
            +
             | 
| 127 | 
            +
                Args:
         | 
| 128 | 
            +
                    requirement: The name of a feature to require or an iterable of
         | 
| 129 | 
            +
                        feature names.
         | 
| 130 | 
            +
                    experiment: An alias for `requirement`.
         | 
| 131 | 
            +
             | 
| 132 | 
            +
                Raises:
         | 
| 133 | 
            +
                    wandb.errors.UnsupportedError: If a feature name is unknown.
         | 
| 134 | 
            +
                """
         | 
| 135 | 
            +
                ...
         | 
| 136 | 
            +
             | 
| 117 137 | 
             
            def setup(settings: Settings | None = None) -> _WandbSetup:
         | 
| 118 138 | 
             
                """Prepares W&B for use in the current process and its children.
         | 
| 119 139 |  | 
| @@ -271,10 +291,10 @@ def init( | |
| 271 291 | 
             
                        on the system, such as checking the git root or the current program
         | 
| 272 292 | 
             
                        file. If we can't infer the project name, the project will default to
         | 
| 273 293 | 
             
                        `"uncategorized"`.
         | 
| 274 | 
            -
                    dir:  | 
| 275 | 
            -
                        files  | 
| 276 | 
            -
                         | 
| 277 | 
            -
                         | 
| 294 | 
            +
                    dir: The absolute path to the directory where experiment logs and
         | 
| 295 | 
            +
                        metadata files are stored. If not specified, this defaults
         | 
| 296 | 
            +
                        to the `./wandb` directory. Note that this does not affect the
         | 
| 297 | 
            +
                        location where artifacts are stored when calling `download()`.
         | 
| 278 298 | 
             
                    id: A unique identifier for this run, used for resuming. It must be unique
         | 
| 279 299 | 
             
                        within the project and cannot be reused once a run is deleted. The
         | 
| 280 300 | 
             
                        identifier must not contain any of the following special characters:
         | 
| @@ -0,0 +1,21 @@ | |
| 1 | 
            +
            # Generated by ariadne-codegen
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            from .base import Base, GQLBase, GQLId, SerializedToJson, Typename
         | 
| 4 | 
            +
            from .operations import SERVER_FEATURES_QUERY_GQL
         | 
| 5 | 
            +
            from .server_features_query import (
         | 
| 6 | 
            +
                ServerFeaturesQuery,
         | 
| 7 | 
            +
                ServerFeaturesQueryServerInfo,
         | 
| 8 | 
            +
                ServerFeaturesQueryServerInfoFeatures,
         | 
| 9 | 
            +
            )
         | 
| 10 | 
            +
             | 
| 11 | 
            +
            __all__ = [
         | 
| 12 | 
            +
                "Base",
         | 
| 13 | 
            +
                "GQLBase",
         | 
| 14 | 
            +
                "GQLId",
         | 
| 15 | 
            +
                "SerializedToJson",
         | 
| 16 | 
            +
                "Typename",
         | 
| 17 | 
            +
                "SERVER_FEATURES_QUERY_GQL",
         | 
| 18 | 
            +
                "ServerFeaturesQuery",
         | 
| 19 | 
            +
                "ServerFeaturesQueryServerInfo",
         | 
| 20 | 
            +
                "ServerFeaturesQueryServerInfoFeatures",
         | 
| 21 | 
            +
            ]
         | 
| @@ -0,0 +1,128 @@ | |
| 1 | 
            +
            # Generated by ariadne-codegen
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            from __future__ import annotations
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            from typing import Any, Literal, TypeVar
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            from pydantic import BaseModel, ConfigDict, Field, Json, ValidationError, WrapValidator
         | 
| 8 | 
            +
            from pydantic.alias_generators import to_camel
         | 
| 9 | 
            +
            from pydantic.main import IncEx
         | 
| 10 | 
            +
            from pydantic_core import to_json
         | 
| 11 | 
            +
            from pydantic_core.core_schema import ValidatorFunctionWrapHandler
         | 
| 12 | 
            +
             | 
| 13 | 
            +
            from .typing_compat import Annotated, override
         | 
| 14 | 
            +
             | 
| 15 | 
            +
             | 
| 16 | 
            +
            # Base class for all automation classes/types.
         | 
| 17 | 
            +
            # Omitted from docstring to avoid inclusion in generated docs.
         | 
| 18 | 
            +
            class Base(BaseModel):
         | 
| 19 | 
            +
                model_config = ConfigDict(
         | 
| 20 | 
            +
                    populate_by_name=True,
         | 
| 21 | 
            +
                    validate_assignment=True,
         | 
| 22 | 
            +
                    validate_default=True,
         | 
| 23 | 
            +
                    extra="forbid",
         | 
| 24 | 
            +
                    alias_generator=to_camel,
         | 
| 25 | 
            +
                    use_attribute_docstrings=True,
         | 
| 26 | 
            +
                    from_attributes=True,
         | 
| 27 | 
            +
                    revalidate_instances="always",
         | 
| 28 | 
            +
                )
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                @override
         | 
| 31 | 
            +
                def model_dump(
         | 
| 32 | 
            +
                    self,
         | 
| 33 | 
            +
                    *,
         | 
| 34 | 
            +
                    mode: Literal["json", "python"] | str = "json",  # NOTE: changed default
         | 
| 35 | 
            +
                    include: IncEx | None = None,
         | 
| 36 | 
            +
                    exclude: IncEx | None = None,
         | 
| 37 | 
            +
                    context: dict[str, Any] | None = None,
         | 
| 38 | 
            +
                    by_alias: bool = True,  # NOTE: changed default
         | 
| 39 | 
            +
                    exclude_unset: bool = False,
         | 
| 40 | 
            +
                    exclude_defaults: bool = False,
         | 
| 41 | 
            +
                    exclude_none: bool = False,
         | 
| 42 | 
            +
                    round_trip: bool = True,  # NOTE: changed default
         | 
| 43 | 
            +
                    warnings: bool | Literal["none", "warn", "error"] = True,
         | 
| 44 | 
            +
                    serialize_as_any: bool = False,
         | 
| 45 | 
            +
                ) -> dict[str, Any]:
         | 
| 46 | 
            +
                    return super().model_dump(
         | 
| 47 | 
            +
                        mode=mode,
         | 
| 48 | 
            +
                        include=include,
         | 
| 49 | 
            +
                        exclude=exclude,
         | 
| 50 | 
            +
                        context=context,
         | 
| 51 | 
            +
                        by_alias=by_alias,
         | 
| 52 | 
            +
                        exclude_unset=exclude_unset,
         | 
| 53 | 
            +
                        exclude_defaults=exclude_defaults,
         | 
| 54 | 
            +
                        exclude_none=exclude_none,
         | 
| 55 | 
            +
                        round_trip=round_trip,
         | 
| 56 | 
            +
                        warnings=warnings,
         | 
| 57 | 
            +
                        serialize_as_any=serialize_as_any,
         | 
| 58 | 
            +
                    )
         | 
| 59 | 
            +
             | 
| 60 | 
            +
                @override
         | 
| 61 | 
            +
                def model_dump_json(
         | 
| 62 | 
            +
                    self,
         | 
| 63 | 
            +
                    *,
         | 
| 64 | 
            +
                    indent: int | None = None,
         | 
| 65 | 
            +
                    include: IncEx | None = None,
         | 
| 66 | 
            +
                    exclude: IncEx | None = None,
         | 
| 67 | 
            +
                    context: dict[str, Any] | None = None,
         | 
| 68 | 
            +
                    by_alias: bool = True,  # NOTE: changed default
         | 
| 69 | 
            +
                    exclude_unset: bool = False,
         | 
| 70 | 
            +
                    exclude_defaults: bool = False,
         | 
| 71 | 
            +
                    exclude_none: bool = False,
         | 
| 72 | 
            +
                    round_trip: bool = True,  # NOTE: changed default
         | 
| 73 | 
            +
                    warnings: bool | Literal["none", "warn", "error"] = True,
         | 
| 74 | 
            +
                    serialize_as_any: bool = False,
         | 
| 75 | 
            +
                ) -> str:
         | 
| 76 | 
            +
                    return super().model_dump_json(
         | 
| 77 | 
            +
                        indent=indent,
         | 
| 78 | 
            +
                        include=include,
         | 
| 79 | 
            +
                        exclude=exclude,
         | 
| 80 | 
            +
                        context=context,
         | 
| 81 | 
            +
                        by_alias=by_alias,
         | 
| 82 | 
            +
                        exclude_unset=exclude_unset,
         | 
| 83 | 
            +
                        exclude_defaults=exclude_defaults,
         | 
| 84 | 
            +
                        exclude_none=exclude_none,
         | 
| 85 | 
            +
                        round_trip=round_trip,
         | 
| 86 | 
            +
                        warnings=warnings,
         | 
| 87 | 
            +
                        serialize_as_any=serialize_as_any,
         | 
| 88 | 
            +
                    )
         | 
| 89 | 
            +
             | 
| 90 | 
            +
             | 
| 91 | 
            +
            # Base class with extra customization for GQL generated types.
         | 
| 92 | 
            +
            # Omitted from docstring to avoid inclusion in generated docs.
         | 
| 93 | 
            +
            class GQLBase(Base):
         | 
| 94 | 
            +
                model_config = ConfigDict(
         | 
| 95 | 
            +
                    extra="ignore",
         | 
| 96 | 
            +
                    protected_namespaces=(),
         | 
| 97 | 
            +
                )
         | 
| 98 | 
            +
             | 
| 99 | 
            +
             | 
| 100 | 
            +
            # ------------------------------------------------------------------------------
         | 
| 101 | 
            +
            # Reusable annotations for field types
         | 
| 102 | 
            +
            T = TypeVar("T")
         | 
| 103 | 
            +
             | 
| 104 | 
            +
            GQLId = Annotated[
         | 
| 105 | 
            +
                str,
         | 
| 106 | 
            +
                Field(repr=False, strict=True, frozen=True),
         | 
| 107 | 
            +
            ]
         | 
| 108 | 
            +
             | 
| 109 | 
            +
            Typename = Annotated[
         | 
| 110 | 
            +
                T,
         | 
| 111 | 
            +
                Field(repr=False, alias="__typename", frozen=True),
         | 
| 112 | 
            +
            ]
         | 
| 113 | 
            +
             | 
| 114 | 
            +
             | 
| 115 | 
            +
            def validate_maybe_json(v: Any, handler: ValidatorFunctionWrapHandler) -> Any:
         | 
| 116 | 
            +
                """Wraps default Json[...] field validator to allow instantiation with an already-decoded value."""
         | 
| 117 | 
            +
                try:
         | 
| 118 | 
            +
                    return handler(v)
         | 
| 119 | 
            +
                except ValidationError:
         | 
| 120 | 
            +
                    # Try revalidating after properly jsonifying the value
         | 
| 121 | 
            +
                    return handler(to_json(v, by_alias=True, round_trip=True))
         | 
| 122 | 
            +
             | 
| 123 | 
            +
             | 
| 124 | 
            +
            SerializedToJson = Annotated[
         | 
| 125 | 
            +
                Json[T],
         | 
| 126 | 
            +
                # Allow lenient instantiation/validation: incoming data may already be deserialized.
         | 
| 127 | 
            +
                WrapValidator(validate_maybe_json),
         | 
| 128 | 
            +
            ]
         | 
| @@ -0,0 +1,15 @@ | |
| 1 | 
            +
            # Generated by ariadne-codegen
         | 
| 2 | 
            +
            # Source: tools/graphql_codegen/utils/
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            __all__ = ["SERVER_FEATURES_QUERY_GQL"]
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            SERVER_FEATURES_QUERY_GQL = """
         | 
| 7 | 
            +
            query ServerFeaturesQuery {
         | 
| 8 | 
            +
              serverInfo {
         | 
| 9 | 
            +
                features {
         | 
| 10 | 
            +
                  name
         | 
| 11 | 
            +
                  isEnabled
         | 
| 12 | 
            +
                }
         | 
| 13 | 
            +
              }
         | 
| 14 | 
            +
            }
         | 
| 15 | 
            +
            """
         | 
| @@ -0,0 +1,27 @@ | |
| 1 | 
            +
            # Generated by ariadne-codegen
         | 
| 2 | 
            +
            # Source: tools/graphql_codegen/utils/
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            from __future__ import annotations
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            from typing import List, Optional
         | 
| 7 | 
            +
             | 
| 8 | 
            +
            from pydantic import Field
         | 
| 9 | 
            +
             | 
| 10 | 
            +
            from .base import GQLBase
         | 
| 11 | 
            +
             | 
| 12 | 
            +
             | 
| 13 | 
            +
            class ServerFeaturesQuery(GQLBase):
         | 
| 14 | 
            +
                server_info: Optional["ServerFeaturesQueryServerInfo"] = Field(alias="serverInfo")
         | 
| 15 | 
            +
             | 
| 16 | 
            +
             | 
| 17 | 
            +
            class ServerFeaturesQueryServerInfo(GQLBase):
         | 
| 18 | 
            +
                features: List[Optional["ServerFeaturesQueryServerInfoFeatures"]]
         | 
| 19 | 
            +
             | 
| 20 | 
            +
             | 
| 21 | 
            +
            class ServerFeaturesQueryServerInfoFeatures(GQLBase):
         | 
| 22 | 
            +
                name: str
         | 
| 23 | 
            +
                is_enabled: bool = Field(alias="isEnabled")
         | 
| 24 | 
            +
             | 
| 25 | 
            +
             | 
| 26 | 
            +
            ServerFeaturesQuery.model_rebuild()
         | 
| 27 | 
            +
            ServerFeaturesQueryServerInfo.model_rebuild()
         | 
| @@ -0,0 +1,14 @@ | |
| 1 | 
            +
            # Generated by ariadne-codegen
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            """Definitions to ensure compatibility with all supported python versions."""
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            import sys
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            if sys.version_info >= (3, 12):
         | 
| 8 | 
            +
                from typing import Annotated, override
         | 
| 9 | 
            +
            else:
         | 
| 10 | 
            +
                from typing_extensions import Annotated, override
         | 
| 11 | 
            +
             | 
| 12 | 
            +
             | 
| 13 | 
            +
            Annnotated = Annotated
         | 
| 14 | 
            +
            override = override
         | 
    
        wandb/apis/public/api.py
    CHANGED
    
    | @@ -25,8 +25,15 @@ import wandb | |
| 25 25 | 
             
            from wandb import env, util
         | 
| 26 26 | 
             
            from wandb.apis import public
         | 
| 27 27 | 
             
            from wandb.apis.normalize import normalize_exceptions
         | 
| 28 | 
            +
            from wandb.apis.public._generated import SERVER_FEATURES_QUERY_GQL, ServerFeaturesQuery
         | 
| 28 29 | 
             
            from wandb.apis.public.const import RETRY_TIMEDELTA
         | 
| 29 | 
            -
            from wandb.apis.public. | 
| 30 | 
            +
            from wandb.apis.public.registries import Registries
         | 
| 31 | 
            +
            from wandb.apis.public.utils import (
         | 
| 32 | 
            +
                PathType,
         | 
| 33 | 
            +
                fetch_org_from_settings_or_entity,
         | 
| 34 | 
            +
                parse_org_from_registry_path,
         | 
| 35 | 
            +
            )
         | 
| 36 | 
            +
            from wandb.proto.wandb_internal_pb2 import ServerFeature
         | 
| 30 37 | 
             
            from wandb.sdk.artifacts._validators import is_artifact_registry_project
         | 
| 31 38 | 
             
            from wandb.sdk.internal.internal_api import Api as InternalApi
         | 
| 32 39 | 
             
            from wandb.sdk.internal.thread_local_settings import _thread_local_api_settings
         | 
| @@ -248,6 +255,9 @@ class Api: | |
| 248 255 | 
             
                        self.settings["entity"] = _overrides["username"]
         | 
| 249 256 | 
             
                    self.settings["base_url"] = self.settings["base_url"].rstrip("/")
         | 
| 250 257 |  | 
| 258 | 
            +
                    if "organization" in _overrides:
         | 
| 259 | 
            +
                        self.settings["organization"] = _overrides["organization"]
         | 
| 260 | 
            +
             | 
| 251 261 | 
             
                    self._viewer = None
         | 
| 252 262 | 
             
                    self._projects = {}
         | 
| 253 263 | 
             
                    self._runs = {}
         | 
| @@ -279,6 +289,7 @@ class Api: | |
| 279 289 | 
             
                        )
         | 
| 280 290 | 
             
                    )
         | 
| 281 291 | 
             
                    self._client = RetryingClient(self._base_client)
         | 
| 292 | 
            +
                    self._server_features_cache = None
         | 
| 282 293 |  | 
| 283 294 | 
             
                def create_project(self, name: str, entity: str) -> None:
         | 
| 284 295 | 
             
                    """Create a new project.
         | 
| @@ -900,12 +911,46 @@ class Api: | |
| 900 911 | 
             
                ):
         | 
| 901 912 | 
             
                    """Return a set of runs from a project that match the filters provided.
         | 
| 902 913 |  | 
| 903 | 
            -
                     | 
| 914 | 
            +
                    Fields you can filter by include:
         | 
| 915 | 
            +
                    - `createdAt`: The timestamp when the run was created. (in ISO 8601 format, e.g. "2023-01-01T12:00:00Z")
         | 
| 916 | 
            +
                    - `displayName`: The human-readable display name of the run. (e.g. "eager-fox-1")
         | 
| 917 | 
            +
                    - `duration`: The total runtime of the run in seconds.
         | 
| 918 | 
            +
                    - `group`: The group name used to organize related runs together.
         | 
| 919 | 
            +
                    - `host`: The hostname where the run was executed.
         | 
| 920 | 
            +
                    - `jobType`: The type of job or purpose of the run.
         | 
| 921 | 
            +
                    - `name`: The unique identifier of the run. (e.g. "a1b2cdef")
         | 
| 922 | 
            +
                    - `state`: The current state of the run.
         | 
| 923 | 
            +
                    - `tags`: The tags associated with the run.
         | 
| 924 | 
            +
                    - `username`: The username of the user who initiated the run
         | 
| 925 | 
            +
             | 
| 926 | 
            +
                    Additionally, you can filter by items in the run config or summary metrics.
         | 
| 927 | 
            +
                    Such as `config.experiment_name`, `summary_metrics.loss`, etc.
         | 
| 928 | 
            +
             | 
| 929 | 
            +
                    For more complex filtering, you can use MongoDB query operators.
         | 
| 930 | 
            +
                    For details, see: https://docs.mongodb.com/manual/reference/operator/query
         | 
| 931 | 
            +
                    The following operations are supported:
         | 
| 932 | 
            +
                    - `$and`
         | 
| 933 | 
            +
                    - `$or`
         | 
| 934 | 
            +
                    - `$nor`
         | 
| 935 | 
            +
                    - `$eq`
         | 
| 936 | 
            +
                    - `$ne`
         | 
| 937 | 
            +
                    - `$gt`
         | 
| 938 | 
            +
                    - `$gte`
         | 
| 939 | 
            +
                    - `$lt`
         | 
| 940 | 
            +
                    - `$lte`
         | 
| 941 | 
            +
                    - `$in`
         | 
| 942 | 
            +
                    - `$nin`
         | 
| 943 | 
            +
                    - `$exists`
         | 
| 944 | 
            +
                    - `$regex`
         | 
| 945 | 
            +
             | 
| 904 946 |  | 
| 905 947 | 
             
                    Examples:
         | 
| 906 948 | 
             
                        Find runs in my_project where config.experiment_name has been set to "foo"
         | 
| 907 949 | 
             
                        ```
         | 
| 908 | 
            -
                        api.runs( | 
| 950 | 
            +
                        api.runs(
         | 
| 951 | 
            +
                            path="my_entity/my_project",
         | 
| 952 | 
            +
                            filters={"config.experiment_name": "foo"},
         | 
| 953 | 
            +
                        )
         | 
| 909 954 | 
             
                        ```
         | 
| 910 955 |  | 
| 911 956 | 
             
                        Find runs in my_project where config.experiment_name has been set to "foo" or "bar"
         | 
| @@ -932,7 +977,24 @@ class Api: | |
| 932 977 | 
             
                        Find runs in my_project where the run name matches a regex (anchors are not supported)
         | 
| 933 978 | 
             
                        ```
         | 
| 934 979 | 
             
                        api.runs(
         | 
| 935 | 
            -
                            path="my_entity/my_project", | 
| 980 | 
            +
                            path="my_entity/my_project",
         | 
| 981 | 
            +
                            filters={"display_name": {"$regex": "^foo.*"}},
         | 
| 982 | 
            +
                        )
         | 
| 983 | 
            +
                        ```
         | 
| 984 | 
            +
             | 
| 985 | 
            +
                        Find runs in my_project where config.experiment contains a nested field "category" with value "testing"
         | 
| 986 | 
            +
                        ```
         | 
| 987 | 
            +
                        api.runs(
         | 
| 988 | 
            +
                            path="my_entity/my_project",
         | 
| 989 | 
            +
                            filters={"config.experiment.category": "testing"},
         | 
| 990 | 
            +
                        )
         | 
| 991 | 
            +
                        ```
         | 
| 992 | 
            +
             | 
| 993 | 
            +
                        Find runs in my_project with a loss value of 0.5 nested in a dictionary under model1 in the summary metrics
         | 
| 994 | 
            +
                        ```
         | 
| 995 | 
            +
                        api.runs(
         | 
| 996 | 
            +
                            path="my_entity/my_project",
         | 
| 997 | 
            +
                            filters={"summary_metrics.model1.loss": 0.5},
         | 
| 936 998 | 
             
                        )
         | 
| 937 999 | 
             
                        ```
         | 
| 938 1000 |  | 
| @@ -947,8 +1009,6 @@ class Api: | |
| 947 1009 | 
             
                            You can filter by run properties such as config.key, summary_metrics.key, state, entity, createdAt, etc.
         | 
| 948 1010 | 
             
                            For example: `{"config.experiment_name": "foo"}` would find runs with a config entry
         | 
| 949 1011 | 
             
                                of experiment name set to "foo"
         | 
| 950 | 
            -
                            You can compose operations to make more complicated queries,
         | 
| 951 | 
            -
                                see Reference for the language is at  https://docs.mongodb.com/manual/reference/operator/query
         | 
| 952 1012 | 
             
                        order: (str) Order can be `created_at`, `heartbeat_at`, `config.*.value`, or `summary_metrics.*`.
         | 
| 953 1013 | 
             
                            If you prepend order with a + order is ascending.
         | 
| 954 1014 | 
             
                            If you prepend order with a - order is descending (default).
         | 
| @@ -1139,6 +1199,12 @@ class Api: | |
| 1139 1199 | 
             
                        entity = InternalApi()._resolve_org_entity_name(
         | 
| 1140 1200 | 
             
                            entity=settings_entity, organization=org
         | 
| 1141 1201 | 
             
                        )
         | 
| 1202 | 
            +
             | 
| 1203 | 
            +
                    if entity is None:
         | 
| 1204 | 
            +
                        raise ValueError(
         | 
| 1205 | 
            +
                            "Could not determine entity. Please include the entity as part of the collection name path."
         | 
| 1206 | 
            +
                        )
         | 
| 1207 | 
            +
             | 
| 1142 1208 | 
             
                    return public.ArtifactCollection(
         | 
| 1143 1209 | 
             
                        self.client, entity, project, collection_name, type_name
         | 
| 1144 1210 | 
             
                    )
         | 
| @@ -1211,6 +1277,12 @@ class Api: | |
| 1211 1277 | 
             
                        entity = InternalApi()._resolve_org_entity_name(
         | 
| 1212 1278 | 
             
                            entity=settings_entity, organization=organization
         | 
| 1213 1279 | 
             
                        )
         | 
| 1280 | 
            +
             | 
| 1281 | 
            +
                    if entity is None:
         | 
| 1282 | 
            +
                        raise ValueError(
         | 
| 1283 | 
            +
                            "Could not determine entity. Please include the entity as part of the artifact name path."
         | 
| 1284 | 
            +
                        )
         | 
| 1285 | 
            +
             | 
| 1214 1286 | 
             
                    artifact = wandb.Artifact._from_name(
         | 
| 1215 1287 | 
             
                        entity=entity,
         | 
| 1216 1288 | 
             
                        project=project,
         | 
| @@ -1385,3 +1457,117 @@ class Api: | |
| 1385 1457 | 
             
                        return True
         | 
| 1386 1458 | 
             
                    except wandb.errors.CommError:
         | 
| 1387 1459 | 
             
                        return False
         | 
| 1460 | 
            +
             | 
| 1461 | 
            +
                def registries(
         | 
| 1462 | 
            +
                    self,
         | 
| 1463 | 
            +
                    organization: Optional[str] = None,
         | 
| 1464 | 
            +
                    filter: Optional[Dict[str, Any]] = None,
         | 
| 1465 | 
            +
                ) -> Registries:
         | 
| 1466 | 
            +
                    """Returns a Registry iterator.
         | 
| 1467 | 
            +
             | 
| 1468 | 
            +
                    Use the iterator to search and filter registries, collections,
         | 
| 1469 | 
            +
                    or artifact versions across your organization's registry.
         | 
| 1470 | 
            +
             | 
| 1471 | 
            +
                    Examples:
         | 
| 1472 | 
            +
                        Find all registries with the names that contain "model"
         | 
| 1473 | 
            +
                        ```python
         | 
| 1474 | 
            +
                        import wandb
         | 
| 1475 | 
            +
             | 
| 1476 | 
            +
                        api = wandb.Api()  # specify an org if your entity belongs to multiple orgs
         | 
| 1477 | 
            +
                        api.registries(filter={"name": {"$regex": "model"}})
         | 
| 1478 | 
            +
                        ```
         | 
| 1479 | 
            +
             | 
| 1480 | 
            +
                        Find all collections in the registries with the name "my_collection" and the tag "my_tag"
         | 
| 1481 | 
            +
                        ```python
         | 
| 1482 | 
            +
                        api.registries().collections(filter={"name": "my_collection", "tag": "my_tag"})
         | 
| 1483 | 
            +
                        ```
         | 
| 1484 | 
            +
             | 
| 1485 | 
            +
                        Find all artifact versions in the registries with a collection name that contains "my_collection" and a version that has the alias "best"
         | 
| 1486 | 
            +
                        ```python
         | 
| 1487 | 
            +
                        api.registries().collections(
         | 
| 1488 | 
            +
                            filter={"name": {"$regex": "my_collection"}}
         | 
| 1489 | 
            +
                        ).versions(filter={"alias": "best"})
         | 
| 1490 | 
            +
                        ```
         | 
| 1491 | 
            +
             | 
| 1492 | 
            +
                        Find all artifact versions in the registries that contain "model" and have the tag "prod" or alias "best"
         | 
| 1493 | 
            +
                        ```python
         | 
| 1494 | 
            +
                        api.registries(filter={"name": {"$regex": "model"}}).versions(
         | 
| 1495 | 
            +
                            filter={"$or": [{"tag": "prod"}, {"alias": "best"}]}
         | 
| 1496 | 
            +
                        )
         | 
| 1497 | 
            +
                        ```
         | 
| 1498 | 
            +
             | 
| 1499 | 
            +
                    Args:
         | 
| 1500 | 
            +
                        organization: (str, optional) The organization of the registry to fetch.
         | 
| 1501 | 
            +
                            If not specified, use the organization specified in the user's settings.
         | 
| 1502 | 
            +
                        filter: (dict, optional) MongoDB-style filter to apply to each object in the registry iterator.
         | 
| 1503 | 
            +
                            Fields available to filter for collections are
         | 
| 1504 | 
            +
                                `name`, `description`, `created_at`, `updated_at`.
         | 
| 1505 | 
            +
                            Fields available to filter for collections are
         | 
| 1506 | 
            +
                                `name`, `tag`, `description`, `created_at`, `updated_at`
         | 
| 1507 | 
            +
                            Fields available to filter for versions are
         | 
| 1508 | 
            +
                                `tag`, `alias`, `created_at`, `updated_at`, `metadata`
         | 
| 1509 | 
            +
             | 
| 1510 | 
            +
                    Returns:
         | 
| 1511 | 
            +
                        A registry iterator.
         | 
| 1512 | 
            +
                    """
         | 
| 1513 | 
            +
                    if not self._check_server_feature_with_fallback(
         | 
| 1514 | 
            +
                        ServerFeature.ARTIFACT_REGISTRY_SEARCH
         | 
| 1515 | 
            +
                    ):
         | 
| 1516 | 
            +
                        raise RuntimeError(
         | 
| 1517 | 
            +
                            "Registry search API is not enabled on this wandb server version. "
         | 
| 1518 | 
            +
                            "Please upgrade your server version or contact support at support@wandb.com."
         | 
| 1519 | 
            +
                        )
         | 
| 1520 | 
            +
             | 
| 1521 | 
            +
                    organization = organization or fetch_org_from_settings_or_entity(
         | 
| 1522 | 
            +
                        self.settings, self.default_entity
         | 
| 1523 | 
            +
                    )
         | 
| 1524 | 
            +
                    return Registries(self.client, organization, filter)
         | 
| 1525 | 
            +
             | 
| 1526 | 
            +
                def _check_server_feature(self, feature: ServerFeature) -> bool:
         | 
| 1527 | 
            +
                    """Check if a server feature is enabled.
         | 
| 1528 | 
            +
             | 
| 1529 | 
            +
                    Args:
         | 
| 1530 | 
            +
                        feature (ServerFeature): The feature to check.
         | 
| 1531 | 
            +
             | 
| 1532 | 
            +
                    Returns:
         | 
| 1533 | 
            +
                        bool: True if the feature is enabled, False otherwise.
         | 
| 1534 | 
            +
             | 
| 1535 | 
            +
                    Raises:
         | 
| 1536 | 
            +
                        Exception: If server doesn't support feature queries or other errors occur
         | 
| 1537 | 
            +
                    """
         | 
| 1538 | 
            +
                    if self._server_features_cache is None:
         | 
| 1539 | 
            +
                        response = self.client.execute(gql(SERVER_FEATURES_QUERY_GQL))
         | 
| 1540 | 
            +
                        self._server_features_cache = ServerFeaturesQuery.model_validate(response)
         | 
| 1541 | 
            +
             | 
| 1542 | 
            +
                    feature_name = ServerFeature.Name(feature)
         | 
| 1543 | 
            +
                    if (
         | 
| 1544 | 
            +
                        self._server_features_cache
         | 
| 1545 | 
            +
                        and self._server_features_cache.server_info
         | 
| 1546 | 
            +
                        and self._server_features_cache.server_info.features
         | 
| 1547 | 
            +
                    ):
         | 
| 1548 | 
            +
                        for feature_info in self._server_features_cache.server_info.features:
         | 
| 1549 | 
            +
                            if feature_info and feature_info.name == feature_name:
         | 
| 1550 | 
            +
                                return feature_info.is_enabled
         | 
| 1551 | 
            +
             | 
| 1552 | 
            +
                    return False
         | 
| 1553 | 
            +
             | 
| 1554 | 
            +
                def _check_server_feature_with_fallback(self, feature: ServerFeature) -> bool:
         | 
| 1555 | 
            +
                    """Wrapper around check_server_feature that warns and returns False for older unsupported servers.
         | 
| 1556 | 
            +
             | 
| 1557 | 
            +
                    Good to use for features that have a fallback mechanism for older servers.
         | 
| 1558 | 
            +
             | 
| 1559 | 
            +
                    Args:
         | 
| 1560 | 
            +
                        feature (ServerFeature): The feature to check.
         | 
| 1561 | 
            +
             | 
| 1562 | 
            +
                    Returns:
         | 
| 1563 | 
            +
                        bool: True if the feature is enabled, False otherwise.
         | 
| 1564 | 
            +
             | 
| 1565 | 
            +
                    Exceptions:
         | 
| 1566 | 
            +
                        Exception: If an error other than the server not supporting feature queries occurs.
         | 
| 1567 | 
            +
                    """
         | 
| 1568 | 
            +
                    try:
         | 
| 1569 | 
            +
                        return self._check_server_feature(feature)
         | 
| 1570 | 
            +
                    except Exception as e:
         | 
| 1571 | 
            +
                        if 'Cannot query field "features" on type "ServerInfo".' in str(e):
         | 
| 1572 | 
            +
                            return False
         | 
| 1573 | 
            +
                        raise e
         | 
    
        wandb/apis/public/artifacts.py
    CHANGED
    
    | @@ -12,56 +12,16 @@ from wandb.apis import public | |
| 12 12 | 
             
            from wandb.apis.normalize import normalize_exceptions
         | 
| 13 13 | 
             
            from wandb.apis.paginator import Paginator
         | 
| 14 14 | 
             
            from wandb.errors.term import termlog
         | 
| 15 | 
            +
            from wandb.sdk.artifacts._graphql_fragments import (
         | 
| 16 | 
            +
                ARTIFACT_FILES_FRAGMENT,
         | 
| 17 | 
            +
                ARTIFACTS_TYPES_FRAGMENT,
         | 
| 18 | 
            +
            )
         | 
| 15 19 | 
             
            from wandb.sdk.lib import deprecate
         | 
| 16 20 |  | 
| 17 21 | 
             
            if TYPE_CHECKING:
         | 
| 18 22 | 
             
                from wandb.apis.public import RetryingClient, Run
         | 
| 19 23 |  | 
| 20 24 |  | 
| 21 | 
            -
            ARTIFACTS_TYPES_FRAGMENT = """
         | 
| 22 | 
            -
            fragment ArtifactTypesFragment on ArtifactTypeConnection {
         | 
| 23 | 
            -
                edges {
         | 
| 24 | 
            -
                     node {
         | 
| 25 | 
            -
                         id
         | 
| 26 | 
            -
                         name
         | 
| 27 | 
            -
                         description
         | 
| 28 | 
            -
                         createdAt
         | 
| 29 | 
            -
                     }
         | 
| 30 | 
            -
                     cursor
         | 
| 31 | 
            -
                }
         | 
| 32 | 
            -
                pageInfo {
         | 
| 33 | 
            -
                    endCursor
         | 
| 34 | 
            -
                    hasNextPage
         | 
| 35 | 
            -
                }
         | 
| 36 | 
            -
            }
         | 
| 37 | 
            -
            """
         | 
| 38 | 
            -
             | 
| 39 | 
            -
            # TODO, factor out common file fragment
         | 
| 40 | 
            -
            ARTIFACT_FILES_FRAGMENT = """fragment ArtifactFilesFragment on Artifact {
         | 
| 41 | 
            -
                files(names: $fileNames, after: $fileCursor, first: $fileLimit) {
         | 
| 42 | 
            -
                    edges {
         | 
| 43 | 
            -
                        node {
         | 
| 44 | 
            -
                            id
         | 
| 45 | 
            -
                            name: displayName
         | 
| 46 | 
            -
                            url
         | 
| 47 | 
            -
                            sizeBytes
         | 
| 48 | 
            -
                            storagePath
         | 
| 49 | 
            -
                            mimetype
         | 
| 50 | 
            -
                            updatedAt
         | 
| 51 | 
            -
                            digest
         | 
| 52 | 
            -
                            md5
         | 
| 53 | 
            -
                            directUrl
         | 
| 54 | 
            -
                        }
         | 
| 55 | 
            -
                        cursor
         | 
| 56 | 
            -
                    }
         | 
| 57 | 
            -
                    pageInfo {
         | 
| 58 | 
            -
                        endCursor
         | 
| 59 | 
            -
                        hasNextPage
         | 
| 60 | 
            -
                    }
         | 
| 61 | 
            -
                }
         | 
| 62 | 
            -
            }"""
         | 
| 63 | 
            -
             | 
| 64 | 
            -
             | 
| 65 25 | 
             
            class ArtifactTypes(Paginator):
         | 
| 66 26 | 
             
                QUERY = gql(
         | 
| 67 27 | 
             
                    """
         | 
| @@ -317,6 +277,7 @@ class ArtifactCollection: | |
| 317 277 | 
             
                    project: str,
         | 
| 318 278 | 
             
                    name: str,
         | 
| 319 279 | 
             
                    type: str,
         | 
| 280 | 
            +
                    organization: Optional[str] = None,
         | 
| 320 281 | 
             
                    attrs: Optional[Mapping[str, Any]] = None,
         | 
| 321 282 | 
             
                ):
         | 
| 322 283 | 
             
                    self.client = client
         | 
| @@ -327,11 +288,14 @@ class ArtifactCollection: | |
| 327 288 | 
             
                    self._type = type
         | 
| 328 289 | 
             
                    self._saved_type = type
         | 
| 329 290 | 
             
                    self._attrs = attrs
         | 
| 330 | 
            -
                    self. | 
| 291 | 
            +
                    if self._attrs is None:
         | 
| 292 | 
            +
                        self.load()
         | 
| 331 293 | 
             
                    self._aliases = [a["node"]["alias"] for a in self._attrs["aliases"]["edges"]]
         | 
| 332 294 | 
             
                    self._description = self._attrs["description"]
         | 
| 295 | 
            +
                    self._created_at = self._attrs["createdAt"]
         | 
| 333 296 | 
             
                    self._tags = [a["node"]["name"] for a in self._attrs["tags"]["edges"]]
         | 
| 334 297 | 
             
                    self._saved_tags = copy(self._tags)
         | 
| 298 | 
            +
                    self.organization = organization
         | 
| 335 299 |  | 
| 336 300 | 
             
                @property
         | 
| 337 301 | 
             
                def id(self):
         | 
| @@ -354,6 +318,10 @@ class ArtifactCollection: | |
| 354 318 | 
             
                    """Artifact Collection Aliases."""
         | 
| 355 319 | 
             
                    return self._aliases
         | 
| 356 320 |  | 
| 321 | 
            +
                @property
         | 
| 322 | 
            +
                def created_at(self):
         | 
| 323 | 
            +
                    return self._created_at
         | 
| 324 | 
            +
             | 
| 357 325 | 
             
                def load(self):
         | 
| 358 326 | 
             
                    query = gql(
         | 
| 359 327 | 
             
                        """
         |