wandb 0.19.9__py3-none-musllinux_1_2_aarch64.whl → 0.19.11__py3-none-musllinux_1_2_aarch64.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.
Files changed (156) hide show
  1. wandb/__init__.py +1 -1
  2. wandb/__init__.pyi +6 -3
  3. wandb/_pydantic/__init__.py +14 -8
  4. wandb/_pydantic/base.py +51 -36
  5. wandb/_pydantic/utils.py +73 -0
  6. wandb/_pydantic/v1_compat.py +79 -57
  7. wandb/apis/public/__init__.py +2 -2
  8. wandb/apis/public/api.py +684 -4
  9. wandb/apis/public/artifacts.py +377 -677
  10. wandb/apis/public/automations.py +69 -0
  11. wandb/apis/public/integrations.py +180 -0
  12. wandb/apis/public/projects.py +29 -0
  13. wandb/apis/public/registries/__init__.py +0 -0
  14. wandb/apis/public/registries/_freezable_list.py +179 -0
  15. wandb/apis/public/{registries.py → registries/registries_search.py} +22 -129
  16. wandb/apis/public/registries/registry.py +357 -0
  17. wandb/apis/public/registries/utils.py +140 -0
  18. wandb/apis/public/runs.py +58 -56
  19. wandb/apis/public/utils.py +107 -1
  20. wandb/automations/__init__.py +73 -0
  21. wandb/automations/_filters/__init__.py +40 -0
  22. wandb/automations/_filters/expressions.py +181 -0
  23. wandb/automations/_filters/operators.py +258 -0
  24. wandb/automations/_filters/run_metrics.py +332 -0
  25. wandb/automations/_generated/__init__.py +177 -0
  26. wandb/automations/_generated/create_automation.py +17 -0
  27. wandb/automations/_generated/create_generic_webhook_integration.py +43 -0
  28. wandb/automations/_generated/delete_automation.py +17 -0
  29. wandb/automations/_generated/enums.py +33 -0
  30. wandb/automations/_generated/fragments.py +358 -0
  31. wandb/automations/_generated/generic_webhook_integrations_by_entity.py +22 -0
  32. wandb/automations/_generated/get_automations.py +24 -0
  33. wandb/automations/_generated/get_automations_by_entity.py +26 -0
  34. wandb/automations/_generated/input_types.py +104 -0
  35. wandb/automations/_generated/integrations_by_entity.py +22 -0
  36. wandb/automations/_generated/operations.py +647 -0
  37. wandb/automations/_generated/slack_integrations_by_entity.py +22 -0
  38. wandb/automations/_generated/update_automation.py +17 -0
  39. wandb/automations/_utils.py +237 -0
  40. wandb/automations/_validators.py +165 -0
  41. wandb/automations/actions.py +220 -0
  42. wandb/automations/automations.py +87 -0
  43. wandb/automations/events.py +287 -0
  44. wandb/automations/integrations.py +45 -0
  45. wandb/automations/scopes.py +78 -0
  46. wandb/beta/workflows.py +9 -10
  47. wandb/bin/gpu_stats +0 -0
  48. wandb/bin/wandb-core +0 -0
  49. wandb/cli/cli.py +3 -3
  50. wandb/env.py +11 -0
  51. wandb/integration/keras/keras.py +2 -1
  52. wandb/integration/langchain/wandb_tracer.py +2 -1
  53. wandb/jupyter.py +137 -118
  54. wandb/old/settings.py +4 -1
  55. wandb/old/summary.py +0 -2
  56. wandb/proto/v3/wandb_internal_pb2.py +297 -292
  57. wandb/proto/v3/wandb_settings_pb2.py +2 -2
  58. wandb/proto/v3/wandb_telemetry_pb2.py +10 -10
  59. wandb/proto/v4/wandb_internal_pb2.py +292 -292
  60. wandb/proto/v4/wandb_settings_pb2.py +2 -2
  61. wandb/proto/v4/wandb_telemetry_pb2.py +10 -10
  62. wandb/proto/v5/wandb_internal_pb2.py +292 -292
  63. wandb/proto/v5/wandb_settings_pb2.py +2 -2
  64. wandb/proto/v5/wandb_telemetry_pb2.py +10 -10
  65. wandb/proto/v6/wandb_base_pb2.py +41 -0
  66. wandb/proto/v6/wandb_internal_pb2.py +393 -0
  67. wandb/proto/v6/wandb_server_pb2.py +78 -0
  68. wandb/proto/v6/wandb_settings_pb2.py +58 -0
  69. wandb/proto/v6/wandb_telemetry_pb2.py +52 -0
  70. wandb/proto/wandb_base_pb2.py +2 -0
  71. wandb/proto/wandb_deprecated.py +8 -0
  72. wandb/proto/wandb_internal_pb2.py +3 -1
  73. wandb/proto/wandb_server_pb2.py +2 -0
  74. wandb/proto/wandb_settings_pb2.py +2 -0
  75. wandb/proto/wandb_telemetry_pb2.py +2 -0
  76. wandb/sdk/artifacts/_generated/__init__.py +289 -0
  77. wandb/sdk/artifacts/_generated/add_aliases.py +21 -0
  78. wandb/sdk/artifacts/_generated/artifact_collection_membership_files.py +43 -0
  79. wandb/sdk/artifacts/_generated/artifact_version_files.py +36 -0
  80. wandb/sdk/artifacts/_generated/create_artifact_collection_tag_assignments.py +36 -0
  81. wandb/sdk/artifacts/_generated/delete_aliases.py +21 -0
  82. wandb/sdk/artifacts/_generated/delete_artifact_collection_tag_assignments.py +25 -0
  83. wandb/sdk/artifacts/_generated/delete_artifact_portfolio.py +35 -0
  84. wandb/sdk/artifacts/_generated/delete_artifact_sequence.py +35 -0
  85. wandb/sdk/artifacts/_generated/enums.py +17 -0
  86. wandb/sdk/artifacts/_generated/fetch_linked_artifacts.py +67 -0
  87. wandb/sdk/artifacts/_generated/fragments.py +221 -0
  88. wandb/sdk/artifacts/_generated/input_types.py +28 -0
  89. wandb/sdk/artifacts/_generated/move_artifact_collection.py +35 -0
  90. wandb/sdk/artifacts/_generated/operations.py +611 -0
  91. wandb/sdk/artifacts/_generated/project_artifact_collection.py +101 -0
  92. wandb/sdk/artifacts/_generated/project_artifact_collections.py +33 -0
  93. wandb/sdk/artifacts/_generated/project_artifact_type.py +24 -0
  94. wandb/sdk/artifacts/_generated/project_artifact_types.py +24 -0
  95. wandb/sdk/artifacts/_generated/project_artifacts.py +42 -0
  96. wandb/sdk/artifacts/_generated/run_input_artifacts.py +51 -0
  97. wandb/sdk/artifacts/_generated/run_output_artifacts.py +51 -0
  98. wandb/sdk/artifacts/_generated/update_artifact.py +26 -0
  99. wandb/sdk/artifacts/_generated/update_artifact_portfolio.py +35 -0
  100. wandb/sdk/artifacts/_generated/update_artifact_sequence.py +35 -0
  101. wandb/sdk/artifacts/_graphql_fragments.py +57 -79
  102. wandb/sdk/artifacts/_validators.py +120 -1
  103. wandb/sdk/artifacts/artifact.py +419 -215
  104. wandb/sdk/artifacts/artifact_file_cache.py +4 -6
  105. wandb/sdk/artifacts/artifact_manifest_entry.py +13 -3
  106. wandb/sdk/artifacts/storage_handlers/azure_handler.py +1 -0
  107. wandb/sdk/artifacts/storage_policies/wandb_storage_policy.py +182 -1
  108. wandb/sdk/artifacts/storage_policy.py +3 -0
  109. wandb/sdk/data_types/base_types/media.py +2 -3
  110. wandb/sdk/data_types/base_types/wb_value.py +34 -11
  111. wandb/sdk/data_types/html.py +36 -9
  112. wandb/sdk/data_types/image.py +12 -12
  113. wandb/sdk/data_types/table.py +5 -0
  114. wandb/sdk/data_types/trace_tree.py +2 -0
  115. wandb/sdk/data_types/utils.py +1 -1
  116. wandb/sdk/data_types/video.py +59 -57
  117. wandb/sdk/interface/interface.py +4 -3
  118. wandb/sdk/internal/internal_api.py +21 -31
  119. wandb/sdk/internal/profiler.py +6 -5
  120. wandb/sdk/internal/run.py +13 -6
  121. wandb/sdk/internal/sender.py +5 -2
  122. wandb/sdk/launch/sweeps/utils.py +8 -0
  123. wandb/sdk/lib/apikey.py +25 -4
  124. wandb/sdk/lib/asyncio_compat.py +1 -1
  125. wandb/sdk/lib/deprecate.py +13 -22
  126. wandb/sdk/lib/disabled.py +2 -1
  127. wandb/sdk/lib/printer.py +37 -8
  128. wandb/sdk/lib/printer_asyncio.py +46 -0
  129. wandb/sdk/lib/redirect.py +10 -5
  130. wandb/sdk/projects/_generated/__init__.py +47 -0
  131. wandb/sdk/projects/_generated/delete_project.py +22 -0
  132. wandb/sdk/projects/_generated/enums.py +4 -0
  133. wandb/sdk/projects/_generated/fetch_registry.py +22 -0
  134. wandb/sdk/projects/_generated/fragments.py +41 -0
  135. wandb/sdk/projects/_generated/input_types.py +13 -0
  136. wandb/sdk/projects/_generated/operations.py +88 -0
  137. wandb/sdk/projects/_generated/rename_project.py +27 -0
  138. wandb/sdk/projects/_generated/upsert_registry_project.py +27 -0
  139. wandb/sdk/service/server_sock.py +19 -14
  140. wandb/sdk/service/service.py +18 -8
  141. wandb/sdk/service/streams.py +5 -0
  142. wandb/sdk/verify/verify.py +6 -3
  143. wandb/sdk/wandb_init.py +217 -70
  144. wandb/sdk/wandb_login.py +13 -4
  145. wandb/sdk/wandb_run.py +419 -295
  146. wandb/sdk/wandb_settings.py +27 -10
  147. wandb/sdk/wandb_setup.py +61 -0
  148. wandb/util.py +33 -29
  149. {wandb-0.19.9.dist-info → wandb-0.19.11.dist-info}/METADATA +5 -5
  150. {wandb-0.19.9.dist-info → wandb-0.19.11.dist-info}/RECORD +153 -83
  151. wandb/_globals.py +0 -19
  152. wandb/sdk/internal/_generated/base.py +0 -226
  153. wandb/sdk/internal/_generated/typing_compat.py +0 -14
  154. {wandb-0.19.9.dist-info → wandb-0.19.11.dist-info}/WHEEL +0 -0
  155. {wandb-0.19.9.dist-info → wandb-0.19.11.dist-info}/entry_points.txt +0 -0
  156. {wandb-0.19.9.dist-info → wandb-0.19.11.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,33 @@
1
+ # Generated by ariadne-codegen
2
+ # Source: tools/graphql_codegen/artifacts/
3
+
4
+ from __future__ import annotations
5
+
6
+ from typing import Optional
7
+
8
+ from pydantic import Field
9
+
10
+ from wandb._pydantic import GQLBase
11
+
12
+ from .fragments import ArtifactCollectionsFragment
13
+
14
+
15
+ class ProjectArtifactCollections(GQLBase):
16
+ project: Optional[ProjectArtifactCollectionsProject]
17
+
18
+
19
+ class ProjectArtifactCollectionsProject(GQLBase):
20
+ artifact_type: Optional[ProjectArtifactCollectionsProjectArtifactType] = Field(
21
+ alias="artifactType"
22
+ )
23
+
24
+
25
+ class ProjectArtifactCollectionsProjectArtifactType(GQLBase):
26
+ artifact_collections: Optional[ArtifactCollectionsFragment] = Field(
27
+ alias="artifactCollections"
28
+ )
29
+
30
+
31
+ ProjectArtifactCollections.model_rebuild()
32
+ ProjectArtifactCollectionsProject.model_rebuild()
33
+ ProjectArtifactCollectionsProjectArtifactType.model_rebuild()
@@ -0,0 +1,24 @@
1
+ # Generated by ariadne-codegen
2
+ # Source: tools/graphql_codegen/artifacts/
3
+
4
+ from __future__ import annotations
5
+
6
+ from typing import Optional
7
+
8
+ from pydantic import Field
9
+
10
+ from wandb._pydantic import GQLBase
11
+
12
+ from .fragments import ArtifactTypeFragment
13
+
14
+
15
+ class ProjectArtifactType(GQLBase):
16
+ project: Optional[ProjectArtifactTypeProject]
17
+
18
+
19
+ class ProjectArtifactTypeProject(GQLBase):
20
+ artifact_type: Optional[ArtifactTypeFragment] = Field(alias="artifactType")
21
+
22
+
23
+ ProjectArtifactType.model_rebuild()
24
+ ProjectArtifactTypeProject.model_rebuild()
@@ -0,0 +1,24 @@
1
+ # Generated by ariadne-codegen
2
+ # Source: tools/graphql_codegen/artifacts/
3
+
4
+ from __future__ import annotations
5
+
6
+ from typing import Optional
7
+
8
+ from pydantic import Field
9
+
10
+ from wandb._pydantic import GQLBase
11
+
12
+ from .fragments import ArtifactTypesFragment
13
+
14
+
15
+ class ProjectArtifactTypes(GQLBase):
16
+ project: Optional[ProjectArtifactTypesProject]
17
+
18
+
19
+ class ProjectArtifactTypesProject(GQLBase):
20
+ artifact_types: ArtifactTypesFragment = Field(alias="artifactTypes")
21
+
22
+
23
+ ProjectArtifactTypes.model_rebuild()
24
+ ProjectArtifactTypesProject.model_rebuild()
@@ -0,0 +1,42 @@
1
+ # Generated by ariadne-codegen
2
+ # Source: tools/graphql_codegen/artifacts/
3
+
4
+ from __future__ import annotations
5
+
6
+ from typing import Literal, Optional
7
+
8
+ from pydantic import Field
9
+
10
+ from wandb._pydantic import GQLBase, Typename
11
+
12
+ from .fragments import ArtifactsFragment
13
+
14
+
15
+ class ProjectArtifacts(GQLBase):
16
+ project: Optional[ProjectArtifactsProject]
17
+
18
+
19
+ class ProjectArtifactsProject(GQLBase):
20
+ artifact_type: Optional[ProjectArtifactsProjectArtifactType] = Field(
21
+ alias="artifactType"
22
+ )
23
+
24
+
25
+ class ProjectArtifactsProjectArtifactType(GQLBase):
26
+ artifact_collection: Optional[
27
+ ProjectArtifactsProjectArtifactTypeArtifactCollection
28
+ ] = Field(alias="artifactCollection")
29
+
30
+
31
+ class ProjectArtifactsProjectArtifactTypeArtifactCollection(GQLBase):
32
+ typename__: Typename[
33
+ Literal["ArtifactCollection", "ArtifactPortfolio", "ArtifactSequence"]
34
+ ]
35
+ name: str
36
+ artifacts: Optional[ArtifactsFragment]
37
+
38
+
39
+ ProjectArtifacts.model_rebuild()
40
+ ProjectArtifactsProject.model_rebuild()
41
+ ProjectArtifactsProjectArtifactType.model_rebuild()
42
+ ProjectArtifactsProjectArtifactTypeArtifactCollection.model_rebuild()
@@ -0,0 +1,51 @@
1
+ # Generated by ariadne-codegen
2
+ # Source: tools/graphql_codegen/artifacts/
3
+
4
+ from __future__ import annotations
5
+
6
+ from typing import List, Optional
7
+
8
+ from pydantic import Field
9
+
10
+ from wandb._pydantic import GQLBase
11
+
12
+ from .fragments import ArtifactFragment
13
+
14
+
15
+ class RunInputArtifacts(GQLBase):
16
+ project: Optional[RunInputArtifactsProject]
17
+
18
+
19
+ class RunInputArtifactsProject(GQLBase):
20
+ run: Optional[RunInputArtifactsProjectRun]
21
+
22
+
23
+ class RunInputArtifactsProjectRun(GQLBase):
24
+ input_artifacts: Optional[RunInputArtifactsProjectRunInputArtifacts] = Field(
25
+ alias="inputArtifacts"
26
+ )
27
+
28
+
29
+ class RunInputArtifactsProjectRunInputArtifacts(GQLBase):
30
+ total_count: int = Field(alias="totalCount")
31
+ edges: List[RunInputArtifactsProjectRunInputArtifactsEdges]
32
+ page_info: RunInputArtifactsProjectRunInputArtifactsPageInfo = Field(
33
+ alias="pageInfo"
34
+ )
35
+
36
+
37
+ class RunInputArtifactsProjectRunInputArtifactsEdges(GQLBase):
38
+ node: Optional[ArtifactFragment]
39
+ cursor: str
40
+
41
+
42
+ class RunInputArtifactsProjectRunInputArtifactsPageInfo(GQLBase):
43
+ end_cursor: Optional[str] = Field(alias="endCursor")
44
+ has_next_page: bool = Field(alias="hasNextPage")
45
+
46
+
47
+ RunInputArtifacts.model_rebuild()
48
+ RunInputArtifactsProject.model_rebuild()
49
+ RunInputArtifactsProjectRun.model_rebuild()
50
+ RunInputArtifactsProjectRunInputArtifacts.model_rebuild()
51
+ RunInputArtifactsProjectRunInputArtifactsEdges.model_rebuild()
@@ -0,0 +1,51 @@
1
+ # Generated by ariadne-codegen
2
+ # Source: tools/graphql_codegen/artifacts/
3
+
4
+ from __future__ import annotations
5
+
6
+ from typing import List, Optional
7
+
8
+ from pydantic import Field
9
+
10
+ from wandb._pydantic import GQLBase
11
+
12
+ from .fragments import ArtifactFragment
13
+
14
+
15
+ class RunOutputArtifacts(GQLBase):
16
+ project: Optional[RunOutputArtifactsProject]
17
+
18
+
19
+ class RunOutputArtifactsProject(GQLBase):
20
+ run: Optional[RunOutputArtifactsProjectRun]
21
+
22
+
23
+ class RunOutputArtifactsProjectRun(GQLBase):
24
+ output_artifacts: Optional[RunOutputArtifactsProjectRunOutputArtifacts] = Field(
25
+ alias="outputArtifacts"
26
+ )
27
+
28
+
29
+ class RunOutputArtifactsProjectRunOutputArtifacts(GQLBase):
30
+ total_count: int = Field(alias="totalCount")
31
+ edges: List[RunOutputArtifactsProjectRunOutputArtifactsEdges]
32
+ page_info: RunOutputArtifactsProjectRunOutputArtifactsPageInfo = Field(
33
+ alias="pageInfo"
34
+ )
35
+
36
+
37
+ class RunOutputArtifactsProjectRunOutputArtifactsEdges(GQLBase):
38
+ node: Optional[ArtifactFragment]
39
+ cursor: str
40
+
41
+
42
+ class RunOutputArtifactsProjectRunOutputArtifactsPageInfo(GQLBase):
43
+ end_cursor: Optional[str] = Field(alias="endCursor")
44
+ has_next_page: bool = Field(alias="hasNextPage")
45
+
46
+
47
+ RunOutputArtifacts.model_rebuild()
48
+ RunOutputArtifactsProject.model_rebuild()
49
+ RunOutputArtifactsProjectRun.model_rebuild()
50
+ RunOutputArtifactsProjectRunOutputArtifacts.model_rebuild()
51
+ RunOutputArtifactsProjectRunOutputArtifactsEdges.model_rebuild()
@@ -0,0 +1,26 @@
1
+ # Generated by ariadne-codegen
2
+ # Source: tools/graphql_codegen/artifacts/
3
+
4
+ from __future__ import annotations
5
+
6
+ from typing import Optional
7
+
8
+ from pydantic import Field
9
+
10
+ from wandb._pydantic import GQLBase
11
+
12
+ from .fragments import ArtifactFragment
13
+
14
+
15
+ class UpdateArtifact(GQLBase):
16
+ update_artifact: Optional[UpdateArtifactUpdateArtifact] = Field(
17
+ alias="updateArtifact"
18
+ )
19
+
20
+
21
+ class UpdateArtifactUpdateArtifact(GQLBase):
22
+ artifact: ArtifactFragment
23
+
24
+
25
+ UpdateArtifact.model_rebuild()
26
+ UpdateArtifactUpdateArtifact.model_rebuild()
@@ -0,0 +1,35 @@
1
+ # Generated by ariadne-codegen
2
+ # Source: tools/graphql_codegen/artifacts/
3
+
4
+ from __future__ import annotations
5
+
6
+ from typing import Literal, Optional
7
+
8
+ from pydantic import Field
9
+
10
+ from wandb._pydantic import GQLBase, GQLId, Typename
11
+
12
+
13
+ class UpdateArtifactPortfolio(GQLBase):
14
+ update_artifact_portfolio: Optional[
15
+ UpdateArtifactPortfolioUpdateArtifactPortfolio
16
+ ] = Field(alias="updateArtifactPortfolio")
17
+
18
+
19
+ class UpdateArtifactPortfolioUpdateArtifactPortfolio(GQLBase):
20
+ artifact_collection: UpdateArtifactPortfolioUpdateArtifactPortfolioArtifactCollection = Field(
21
+ alias="artifactCollection"
22
+ )
23
+
24
+
25
+ class UpdateArtifactPortfolioUpdateArtifactPortfolioArtifactCollection(GQLBase):
26
+ typename__: Typename[
27
+ Literal["ArtifactCollection", "ArtifactPortfolio", "ArtifactSequence"]
28
+ ]
29
+ id: GQLId
30
+ name: str
31
+ description: Optional[str]
32
+
33
+
34
+ UpdateArtifactPortfolio.model_rebuild()
35
+ UpdateArtifactPortfolioUpdateArtifactPortfolio.model_rebuild()
@@ -0,0 +1,35 @@
1
+ # Generated by ariadne-codegen
2
+ # Source: tools/graphql_codegen/artifacts/
3
+
4
+ from __future__ import annotations
5
+
6
+ from typing import Literal, Optional
7
+
8
+ from pydantic import Field
9
+
10
+ from wandb._pydantic import GQLBase, GQLId, Typename
11
+
12
+
13
+ class UpdateArtifactSequence(GQLBase):
14
+ update_artifact_sequence: Optional[UpdateArtifactSequenceUpdateArtifactSequence] = (
15
+ Field(alias="updateArtifactSequence")
16
+ )
17
+
18
+
19
+ class UpdateArtifactSequenceUpdateArtifactSequence(GQLBase):
20
+ artifact_collection: UpdateArtifactSequenceUpdateArtifactSequenceArtifactCollection = Field(
21
+ alias="artifactCollection"
22
+ )
23
+
24
+
25
+ class UpdateArtifactSequenceUpdateArtifactSequenceArtifactCollection(GQLBase):
26
+ typename__: Typename[
27
+ Literal["ArtifactCollection", "ArtifactPortfolio", "ArtifactSequence"]
28
+ ]
29
+ id: GQLId
30
+ name: str
31
+ description: Optional[str]
32
+
33
+
34
+ UpdateArtifactSequence.model_rebuild()
35
+ UpdateArtifactSequenceUpdateArtifactSequence.model_rebuild()
@@ -1,62 +1,57 @@
1
+ from __future__ import annotations
2
+
3
+ from textwrap import dedent
4
+
5
+ from wandb_graphql.language.printer import print_ast
6
+
7
+ from wandb.apis.public.utils import gql_compat
1
8
  from wandb.sdk.internal.internal_api import Api as InternalApi
2
9
 
3
- ARTIFACTS_TYPES_FRAGMENT = """
4
- fragment ArtifactTypesFragment on ArtifactTypeConnection {
5
- edges {
6
- node {
7
- id
8
- name
9
- description
10
- createdAt
11
- }
12
- cursor
10
+ OMITTABLE_ARTIFACT_FIELDS = frozenset(
11
+ {
12
+ "ttlDurationSeconds",
13
+ "ttlIsInherited",
14
+ "aliases",
15
+ "tags",
16
+ "historyStep",
13
17
  }
14
- pageInfo {
15
- endCursor
16
- hasNextPage
17
- }
18
- }
19
- """
18
+ )
20
19
 
21
- ARTIFACT_FILES_FRAGMENT = """fragment FilesFragment on FileConnection {
22
- edges {
23
- node {
24
- id
25
- name: displayName
26
- url
27
- sizeBytes
28
- storagePath
29
- mimetype
30
- updatedAt
31
- digest
32
- md5
33
- directUrl
34
- }
35
- cursor
36
- }
37
- pageInfo {
38
- endCursor
39
- hasNextPage
40
- }
41
- }"""
20
+
21
+ def omit_artifact_fields(api: InternalApi) -> set[str]:
22
+ """Return names of Artifact fields to remove from GraphQL requests (for server compatibility)."""
23
+ allowed_fields = set(api.server_artifact_introspection())
24
+ return set(OMITTABLE_ARTIFACT_FIELDS - allowed_fields)
42
25
 
43
26
 
44
27
  def _gql_artifact_fragment(include_aliases: bool = True) -> str:
45
28
  """Return a GraphQL query fragment with all parseable Artifact attributes."""
46
- allowed_fields = set(InternalApi().server_artifact_introspection())
29
+ omit_fields = omit_artifact_fields(api=InternalApi())
47
30
 
48
- supports_ttl = "ttlIsInherited" in allowed_fields
49
- supports_tags = "tags" in allowed_fields
31
+ # Respect the `include_aliases` flag
32
+ if not include_aliases:
33
+ omit_fields.add("aliases")
50
34
 
51
- ttl_duration_seconds = "ttlDurationSeconds" if supports_ttl else ""
52
- ttl_is_inherited = "ttlIsInherited" if supports_ttl else ""
53
-
54
- tags = "tags {name}" if supports_tags else ""
55
-
56
- # The goal is to move all artifact aliases fetches to the membership level in the future
57
- # but this is a quick fix to unblock the registry work
58
- aliases = (
59
- """aliases {
35
+ artifact_fragment_str = dedent(
36
+ """\
37
+ fragment ArtifactFragment on Artifact {
38
+ id
39
+ artifactSequence {
40
+ project {
41
+ entityName
42
+ name
43
+ }
44
+ name
45
+ }
46
+ versionIndex
47
+ artifactType {
48
+ name
49
+ }
50
+ description
51
+ metadata
52
+ ttlDurationSeconds
53
+ ttlIsInherited
54
+ aliases {
60
55
  artifactCollection {
61
56
  project {
62
57
  entityName
@@ -65,43 +60,25 @@ def _gql_artifact_fragment(include_aliases: bool = True) -> str:
65
60
  name
66
61
  }
67
62
  alias
68
- }"""
69
- if include_aliases
70
- else ""
71
- )
72
-
73
- return f"""
74
- fragment ArtifactFragment on Artifact {{
75
- id
76
- artifactSequence {{
77
- project {{
78
- entityName
79
- name
80
- }}
81
- name
82
- }}
83
- versionIndex
84
- artifactType {{
63
+ }
64
+ tags {
85
65
  name
86
- }}
87
- description
88
- metadata
89
- {ttl_duration_seconds}
90
- {ttl_is_inherited}
91
- {aliases}
92
- {tags}
66
+ }
67
+ historyStep
93
68
  state
94
- currentManifest {{
95
- file {{
69
+ currentManifest {
70
+ file {
96
71
  directUrl
97
- }}
98
- }}
72
+ }
73
+ }
99
74
  commitHash
100
75
  fileCount
101
76
  createdAt
102
77
  updatedAt
103
- }}
104
- """
78
+ }"""
79
+ )
80
+ compat_doc = gql_compat(artifact_fragment_str, omit_fields=omit_fields)
81
+ return print_ast(compat_doc)
105
82
 
106
83
 
107
84
  def _gql_registry_fragment() -> str:
@@ -120,5 +97,6 @@ def _gql_registry_fragment() -> str:
120
97
  description
121
98
  createdAt
122
99
  updatedAt
100
+ access
123
101
  }
124
102
  """
@@ -3,9 +3,14 @@
3
3
  from __future__ import annotations
4
4
 
5
5
  import re
6
+ from dataclasses import dataclass, field
6
7
  from functools import wraps
7
- from typing import TYPE_CHECKING, Any, Callable, TypeVar, cast, overload
8
+ from typing import TYPE_CHECKING, Any, Callable, Literal, TypeVar, cast, overload
8
9
 
10
+ from wandb.sdk.artifacts._generated.fragments import (
11
+ ArtifactPortfolioTypeFields,
12
+ ArtifactSequenceTypeFields,
13
+ )
9
14
  from wandb.sdk.artifacts.exceptions import (
10
15
  ArtifactFinalizedError,
11
16
  ArtifactNotLoggedError,
@@ -24,6 +29,41 @@ if TYPE_CHECKING:
24
29
  REGISTRY_PREFIX: Final[str] = "wandb-registry-"
25
30
  MAX_ARTIFACT_METADATA_KEYS: Final[int] = 100
26
31
 
32
+ ARTIFACT_NAME_MAXLEN: Final[int] = 128
33
+ ARTIFACT_NAME_INVALID_CHARS: Final[frozenset[str]] = frozenset({"/"})
34
+
35
+ LINKED_ARTIFACT_COLLECTION_TYPE: Final[str] = ArtifactPortfolioTypeFields.model_fields[
36
+ "typename__"
37
+ ].default
38
+ SOURCE_ARTIFACT_COLLECTION_TYPE: Final[str] = ArtifactSequenceTypeFields.model_fields[
39
+ "typename__"
40
+ ].default
41
+
42
+
43
+ @dataclass
44
+ class _LinkArtifactFields:
45
+ """Keep this list updated with fields where the linked artifact and the source artifact differ."""
46
+
47
+ entity_name: str
48
+ project_name: str
49
+ name: str
50
+ version: str
51
+ aliases: list[str]
52
+
53
+ # These fields shouldn't be set as they should always be
54
+ # these values for a linked artifact
55
+ # These fields shouldn't be set by the user as they should always be these values for a linked artifact
56
+ _is_link: Literal[True] = field(init=False, default=True)
57
+ _linked_artifacts: list[Artifact] = field(init=False, default_factory=list)
58
+
59
+ @property
60
+ def is_link(self) -> bool:
61
+ return self._is_link
62
+
63
+ @property
64
+ def linked_artifacts(self) -> list[Artifact]:
65
+ return self._linked_artifacts
66
+
27
67
 
28
68
  # For mypy checks
29
69
  @overload
@@ -43,6 +83,69 @@ def always_list(obj: Any, base_type: Any = (str, bytes)) -> list[T]:
43
83
  return [obj] if isinstance(obj, base_type) else list(obj)
44
84
 
45
85
 
86
+ def validate_artifact_name(name: str) -> str:
87
+ """Validate the artifact name, returning it if successful.
88
+
89
+ Raises:
90
+ ValueError: If the artifact name is invalid.
91
+ """
92
+ if len(name) > ARTIFACT_NAME_MAXLEN:
93
+ short_name = f"{name[:ARTIFACT_NAME_MAXLEN]} ..."
94
+ raise ValueError(
95
+ f"Artifact name is longer than {ARTIFACT_NAME_MAXLEN} characters: {short_name!r}"
96
+ )
97
+
98
+ if ARTIFACT_NAME_INVALID_CHARS.intersection(name):
99
+ raise ValueError(
100
+ "Artifact names must not contain any of the following characters: "
101
+ f"{', '.join(sorted(ARTIFACT_NAME_INVALID_CHARS))}. Got: {name!r}"
102
+ )
103
+
104
+ return name
105
+
106
+
107
+ INVALID_URL_CHARACTERS = ("/", "\\", "#", "?", "%", ":", "\r", "\n")
108
+
109
+
110
+ def validate_project_name(name: str) -> None:
111
+ """Validates a project name according to W&B rules.
112
+
113
+ Args:
114
+ name: The project name string.
115
+
116
+ Raises:
117
+ ValueError: If the name is invalid (too long or contains invalid characters).
118
+ """
119
+ max_len = 128
120
+
121
+ if len(name) == 0:
122
+ raise ValueError("Project name cannot be empty")
123
+
124
+ registry_name = ""
125
+ if name.startswith(REGISTRY_PREFIX):
126
+ registry_name = name[len(REGISTRY_PREFIX) :]
127
+ if len(registry_name) == 0:
128
+ raise ValueError("Registry name cannot be empty")
129
+
130
+ if len(name) > max_len:
131
+ if registry_name:
132
+ raise ValueError(
133
+ f"Invalid registry name {registry_name!r}, must be {max_len - len(REGISTRY_PREFIX)} characters or less"
134
+ )
135
+ else:
136
+ raise ValueError(
137
+ f"Invalid project name {name!r}, must be {max_len} characters or less"
138
+ )
139
+
140
+ # Find the first occurrence of any invalid character
141
+ if invalid_chars := set(INVALID_URL_CHARACTERS).intersection(name):
142
+ error_name = registry_name or name
143
+ invalid_chars_repr = ", ".join(sorted(map(repr, invalid_chars)))
144
+ raise ValueError(
145
+ f"Invalid project/registry name {error_name!r}, cannot contain characters: {invalid_chars_repr!s}"
146
+ )
147
+
148
+
46
149
  def validate_aliases(aliases: Collection[str] | str) -> list[str]:
47
150
  """Validate the artifact aliases and return them as a list.
48
151
 
@@ -59,6 +162,22 @@ def validate_aliases(aliases: Collection[str] | str) -> list[str]:
59
162
  return aliases_list
60
163
 
61
164
 
165
+ def validate_artifact_types_list(artifact_types: list[str]) -> list[str]:
166
+ """Return True if the artifact types list is valid, False otherwise."""
167
+ artifact_types = always_list(artifact_types)
168
+ invalid_chars = ("/", ":")
169
+ if any(
170
+ char in type or len(type) > 128
171
+ for type in artifact_types
172
+ for char in invalid_chars
173
+ ):
174
+ raise ValueError(
175
+ f"""Artifact types must not contain any of the following characters: {", ".join(invalid_chars)}
176
+ and must be less than equal to 128 characters"""
177
+ )
178
+ return artifact_types
179
+
180
+
62
181
  _VALID_TAG_PATTERN: re.Pattern[str] = re.compile(r"^[-\w]+( +[-\w]+)*$")
63
182
 
64
183