wandb 0.18.5__py3-none-macosx_11_0_arm64.whl → 0.18.6__py3-none-macosx_11_0_arm64.whl

Sign up to get free protection for your applications and to get access to all the features.
Files changed (129) hide show
  1. wandb/__init__.py +2 -2
  2. wandb/__init__.pyi +21 -19
  3. wandb/agents/pyagent.py +1 -1
  4. wandb/apis/importers/wandb.py +1 -1
  5. wandb/apis/normalize.py +2 -18
  6. wandb/apis/public/api.py +122 -62
  7. wandb/apis/public/artifacts.py +8 -3
  8. wandb/apis/public/files.py +17 -2
  9. wandb/apis/public/jobs.py +2 -2
  10. wandb/apis/public/query_generator.py +1 -1
  11. wandb/apis/public/runs.py +8 -8
  12. wandb/apis/public/teams.py +3 -3
  13. wandb/apis/public/users.py +1 -1
  14. wandb/apis/public/utils.py +68 -0
  15. wandb/bin/gpu_stats +0 -0
  16. wandb/bin/wandb-core +0 -0
  17. wandb/cli/cli.py +12 -3
  18. wandb/data_types.py +1 -1
  19. wandb/docker/__init__.py +2 -1
  20. wandb/docker/auth.py +2 -3
  21. wandb/errors/links.py +73 -0
  22. wandb/errors/term.py +7 -6
  23. wandb/filesync/step_prepare.py +1 -1
  24. wandb/filesync/upload_job.py +1 -1
  25. wandb/integration/catboost/catboost.py +2 -2
  26. wandb/integration/diffusers/pipeline_resolver.py +1 -1
  27. wandb/integration/diffusers/resolvers/multimodal.py +6 -6
  28. wandb/integration/diffusers/resolvers/utils.py +1 -1
  29. wandb/integration/fastai/__init__.py +3 -2
  30. wandb/integration/keras/callbacks/metrics_logger.py +1 -1
  31. wandb/integration/keras/callbacks/model_checkpoint.py +1 -1
  32. wandb/integration/keras/keras.py +1 -1
  33. wandb/integration/kfp/kfp_patch.py +1 -1
  34. wandb/integration/lightgbm/__init__.py +2 -2
  35. wandb/integration/magic.py +2 -2
  36. wandb/integration/metaflow/metaflow.py +1 -1
  37. wandb/integration/sacred/__init__.py +1 -1
  38. wandb/integration/sagemaker/auth.py +1 -1
  39. wandb/integration/sklearn/plot/classifier.py +7 -7
  40. wandb/integration/sklearn/plot/clusterer.py +3 -3
  41. wandb/integration/sklearn/plot/regressor.py +3 -3
  42. wandb/integration/sklearn/plot/shared.py +2 -2
  43. wandb/integration/tensorboard/log.py +2 -2
  44. wandb/integration/ultralytics/callback.py +2 -2
  45. wandb/integration/xgboost/xgboost.py +1 -1
  46. wandb/jupyter.py +0 -1
  47. wandb/plot/__init__.py +17 -8
  48. wandb/plot/bar.py +53 -27
  49. wandb/plot/confusion_matrix.py +151 -70
  50. wandb/plot/custom_chart.py +124 -0
  51. wandb/plot/histogram.py +46 -20
  52. wandb/plot/line.py +57 -26
  53. wandb/plot/line_series.py +148 -60
  54. wandb/plot/pr_curve.py +89 -44
  55. wandb/plot/roc_curve.py +82 -37
  56. wandb/plot/scatter.py +53 -20
  57. wandb/plot/viz.py +20 -102
  58. wandb/sdk/artifacts/artifact.py +280 -328
  59. wandb/sdk/artifacts/artifact_manifest.py +10 -9
  60. wandb/sdk/artifacts/artifact_manifest_entry.py +1 -1
  61. wandb/sdk/artifacts/storage_handlers/azure_handler.py +9 -4
  62. wandb/sdk/artifacts/storage_handlers/gcs_handler.py +1 -3
  63. wandb/sdk/artifacts/storage_handlers/s3_handler.py +1 -1
  64. wandb/sdk/artifacts/storage_handlers/wb_artifact_handler.py +2 -2
  65. wandb/sdk/artifacts/storage_handlers/wb_local_artifact_handler.py +1 -1
  66. wandb/sdk/backend/backend.py +0 -1
  67. wandb/sdk/data_types/audio.py +1 -1
  68. wandb/sdk/data_types/base_types/media.py +66 -5
  69. wandb/sdk/data_types/bokeh.py +1 -1
  70. wandb/sdk/data_types/helper_types/bounding_boxes_2d.py +1 -1
  71. wandb/sdk/data_types/helper_types/image_mask.py +2 -2
  72. wandb/sdk/data_types/histogram.py +1 -1
  73. wandb/sdk/data_types/html.py +1 -1
  74. wandb/sdk/data_types/image.py +1 -1
  75. wandb/sdk/data_types/molecule.py +3 -3
  76. wandb/sdk/data_types/object_3d.py +4 -4
  77. wandb/sdk/data_types/plotly.py +1 -1
  78. wandb/sdk/data_types/saved_model.py +0 -1
  79. wandb/sdk/data_types/table.py +7 -7
  80. wandb/sdk/data_types/trace_tree.py +1 -1
  81. wandb/sdk/data_types/video.py +4 -3
  82. wandb/sdk/interface/router.py +0 -2
  83. wandb/sdk/internal/datastore.py +1 -1
  84. wandb/sdk/internal/file_pusher.py +1 -1
  85. wandb/sdk/internal/file_stream.py +4 -4
  86. wandb/sdk/internal/handler.py +3 -2
  87. wandb/sdk/internal/internal.py +1 -1
  88. wandb/sdk/internal/internal_api.py +178 -63
  89. wandb/sdk/internal/job_builder.py +4 -3
  90. wandb/sdk/internal/system/assets/__init__.py +0 -2
  91. wandb/sdk/internal/tb_watcher.py +11 -10
  92. wandb/sdk/launch/_launch.py +4 -3
  93. wandb/sdk/launch/_launch_add.py +2 -2
  94. wandb/sdk/launch/builder/kaniko_builder.py +0 -1
  95. wandb/sdk/launch/create_job.py +1 -0
  96. wandb/sdk/launch/environment/local_environment.py +0 -1
  97. wandb/sdk/launch/errors.py +0 -6
  98. wandb/sdk/launch/registry/local_registry.py +0 -2
  99. wandb/sdk/launch/runner/abstract.py +0 -5
  100. wandb/sdk/launch/sweeps/__init__.py +0 -2
  101. wandb/sdk/launch/sweeps/scheduler.py +0 -2
  102. wandb/sdk/launch/sweeps/scheduler_sweep.py +0 -1
  103. wandb/sdk/lib/apikey.py +3 -3
  104. wandb/sdk/lib/file_stream_utils.py +1 -1
  105. wandb/sdk/lib/filesystem.py +1 -1
  106. wandb/sdk/lib/ipython.py +16 -9
  107. wandb/sdk/lib/mailbox.py +0 -4
  108. wandb/sdk/lib/printer.py +44 -8
  109. wandb/sdk/lib/retry.py +1 -1
  110. wandb/sdk/service/service.py +3 -3
  111. wandb/sdk/service/streams.py +2 -4
  112. wandb/sdk/wandb_init.py +20 -20
  113. wandb/sdk/wandb_login.py +1 -1
  114. wandb/sdk/wandb_require.py +1 -4
  115. wandb/sdk/wandb_run.py +57 -69
  116. wandb/sdk/wandb_settings.py +3 -4
  117. wandb/sdk/wandb_sync.py +2 -1
  118. wandb/util.py +46 -18
  119. wandb/wandb_agent.py +3 -3
  120. wandb/wandb_controller.py +2 -2
  121. {wandb-0.18.5.dist-info → wandb-0.18.6.dist-info}/METADATA +1 -1
  122. {wandb-0.18.5.dist-info → wandb-0.18.6.dist-info}/RECORD +125 -126
  123. wandb/sdk/internal/system/assets/gpu_apple.py +0 -177
  124. wandb/sdk/lib/_wburls_generate.py +0 -25
  125. wandb/sdk/lib/_wburls_generated.py +0 -22
  126. wandb/sdk/lib/wburls.py +0 -46
  127. {wandb-0.18.5.dist-info → wandb-0.18.6.dist-info}/WHEEL +0 -0
  128. {wandb-0.18.5.dist-info → wandb-0.18.6.dist-info}/entry_points.txt +0 -0
  129. {wandb-0.18.5.dist-info → wandb-0.18.6.dist-info}/licenses/LICENSE +0 -0
@@ -22,6 +22,7 @@ from typing import (
22
22
  List,
23
23
  Mapping,
24
24
  MutableMapping,
25
+ NamedTuple,
25
26
  Optional,
26
27
  Sequence,
27
28
  TextIO,
@@ -169,6 +170,50 @@ class _ThreadLocalData(threading.local):
169
170
  self.context = None
170
171
 
171
172
 
173
+ class _OrgNames(NamedTuple):
174
+ entity_name: str
175
+ display_name: str
176
+
177
+
178
+ def _match_org_with_fetched_org_entities(
179
+ organization: str, orgs: Sequence[_OrgNames]
180
+ ) -> str:
181
+ """Match the organization provided in the path with the org entity or org name of the input entity.
182
+
183
+ Args:
184
+ organization: The organization name to match
185
+ orgs: List of tuples containing (org_entity_name, org_display_name)
186
+
187
+ Returns:
188
+ str: The matched org entity name
189
+
190
+ Raises:
191
+ ValueError: If no matching organization is found or if multiple orgs exist without a match
192
+ """
193
+ for org_names in orgs:
194
+ if organization in org_names:
195
+ wandb.termwarn(
196
+ "Registries can be linked/fetched using a shorthand form without specifying the organization name. "
197
+ "Try using shorthand path format: <my_registry_name>/<artifact_name> or "
198
+ "just <my_registry_name> if fetching just the project."
199
+ )
200
+ return org_names.entity_name
201
+
202
+ if len(orgs) == 1:
203
+ raise ValueError(
204
+ f"Expecting the organization name or entity name to match {orgs[0].display_name!r} "
205
+ f"and cannot be linked/fetched with {organization!r}. "
206
+ "Please update the target path with the correct organization name."
207
+ )
208
+
209
+ raise ValueError(
210
+ "Personal entity belongs to multiple organizations "
211
+ f"and cannot be linked/fetched with {organization!r}. "
212
+ "Please update the target path with the correct organization name "
213
+ "or use a team entity in the entity settings."
214
+ )
215
+
216
+
172
217
  class Api:
173
218
  """W&B Internal Api wrapper.
174
219
 
@@ -178,7 +223,7 @@ class Api:
178
223
  directory. If none can be found, we look in the current user's home
179
224
  directory.
180
225
 
181
- Arguments:
226
+ Args:
182
227
  default_settings(dict, optional): If you aren't using a settings
183
228
  file, or you wish to override the section to use in the settings file
184
229
  Override the settings here.
@@ -313,6 +358,7 @@ class Api:
313
358
  self.server_create_artifact_input_info: Optional[List[str]] = None
314
359
  self.server_artifact_fields_info: Optional[List[str]] = None
315
360
  self.server_organization_type_fields_info: Optional[List[str]] = None
361
+ self.server_supports_enabling_artifact_usage_tracking: Optional[bool] = None
316
362
  self._max_cli_version: Optional[str] = None
317
363
  self._server_settings_type: Optional[List[str]] = None
318
364
  self.fail_run_queue_item_input_info: Optional[List[str]] = None
@@ -434,7 +480,7 @@ class Api:
434
480
  def settings(self, key: Optional[str] = None, section: Optional[str] = None) -> Any:
435
481
  """The settings overridden from the wandb/settings file.
436
482
 
437
- Arguments:
483
+ Args:
438
484
  key (str, optional): If provided only this setting is returned
439
485
  section (str, optional): If provided this section of the setting file is
440
486
  used, defaults to "default"
@@ -514,7 +560,7 @@ class Api:
514
560
  ) -> Tuple[str, str]:
515
561
  """Parse a slug into a project and run.
516
562
 
517
- Arguments:
563
+ Args:
518
564
  slug (str): The slug to parse
519
565
  project (str, optional): The project to use, if not provided it will be
520
566
  inferred from the slug
@@ -953,7 +999,7 @@ class Api:
953
999
  def list_projects(self, entity: Optional[str] = None) -> List[Dict[str, str]]:
954
1000
  """List projects in W&B scoped by entity.
955
1001
 
956
- Arguments:
1002
+ Args:
957
1003
  entity (str, optional): The entity to scope this project to.
958
1004
 
959
1005
  Returns:
@@ -985,7 +1031,7 @@ class Api:
985
1031
  def project(self, project: str, entity: Optional[str] = None) -> "_Response":
986
1032
  """Retrieve project.
987
1033
 
988
- Arguments:
1034
+ Args:
989
1035
  project (str): The project to get details for
990
1036
  entity (str, optional): The entity to scope this project to.
991
1037
 
@@ -1020,7 +1066,7 @@ class Api:
1020
1066
  ) -> Dict[str, Any]:
1021
1067
  """Retrieve sweep.
1022
1068
 
1023
- Arguments:
1069
+ Args:
1024
1070
  sweep (str): The sweep to get details for
1025
1071
  specs (str): history specs
1026
1072
  project (str, optional): The project to scope this sweep to.
@@ -1093,7 +1139,7 @@ class Api:
1093
1139
  ) -> List[Dict[str, str]]:
1094
1140
  """List runs in W&B scoped by project.
1095
1141
 
1096
- Arguments:
1142
+ Args:
1097
1143
  project (str): The project to scope the runs to
1098
1144
  entity (str, optional): The entity to scope this project to. Defaults to public models
1099
1145
 
@@ -1134,7 +1180,7 @@ class Api:
1134
1180
  ) -> Tuple[str, Dict[str, Any], Optional[str], Dict[str, Any]]:
1135
1181
  """Get the relevant configs for a run.
1136
1182
 
1137
- Arguments:
1183
+ Args:
1138
1184
  project (str): The project to download, (can include bucket)
1139
1185
  run (str, optional): The run to download
1140
1186
  entity (str, optional): The entity to scope this project to.
@@ -1223,7 +1269,7 @@ class Api:
1223
1269
  ) -> Optional[Dict[str, Any]]:
1224
1270
  """Check if a run exists and get resume information.
1225
1271
 
1226
- Arguments:
1272
+ Args:
1227
1273
  entity (str): The entity to scope this project to.
1228
1274
  project_name (str): The project to download, (can include bucket)
1229
1275
  name (str): The run to download
@@ -1328,7 +1374,7 @@ class Api:
1328
1374
  ) -> Dict[str, Any]:
1329
1375
  """Create a new project.
1330
1376
 
1331
- Arguments:
1377
+ Args:
1332
1378
  project (str): The project to create
1333
1379
  description (str, optional): A description of this project
1334
1380
  entity (str, optional): The entity to scope this project to.
@@ -2156,7 +2202,7 @@ class Api:
2156
2202
  ) -> Tuple[dict, bool, Optional[List]]:
2157
2203
  """Update a run.
2158
2204
 
2159
- Arguments:
2205
+ Args:
2160
2206
  id (str, optional): The existing run to update
2161
2207
  name (str, optional): The name of the run to create
2162
2208
  group (str, optional): Name of the group this run is a part of
@@ -2343,7 +2389,7 @@ class Api:
2343
2389
  ) -> dict:
2344
2390
  """Rewinds a run to a previous state.
2345
2391
 
2346
- Arguments:
2392
+ Args:
2347
2393
  run_name (str): The name of the run to rewind
2348
2394
  metric_name (str): The name of the metric to rewind to
2349
2395
  metric_value (float): The value of the metric to rewind to
@@ -2530,7 +2576,7 @@ class Api:
2530
2576
  ) -> Tuple[str, List[str], Dict[str, Dict[str, Any]]]:
2531
2577
  """Generate temporary resumable upload urls.
2532
2578
 
2533
- Arguments:
2579
+ Args:
2534
2580
  project (str): The project to download
2535
2581
  files (list or dict): The filenames to upload
2536
2582
  run (str, optional): The run to upload to
@@ -2667,7 +2713,7 @@ class Api:
2667
2713
  ) -> Dict[str, Dict[str, str]]:
2668
2714
  """Generate download urls.
2669
2715
 
2670
- Arguments:
2716
+ Args:
2671
2717
  project (str): The project to download
2672
2718
  run (str): The run to upload to
2673
2719
  entity (str, optional): The entity to scope this project to. Defaults to wandb models
@@ -2726,7 +2772,7 @@ class Api:
2726
2772
  ) -> Optional[Dict[str, str]]:
2727
2773
  """Generate download urls.
2728
2774
 
2729
- Arguments:
2775
+ Args:
2730
2776
  project (str): The project to download
2731
2777
  file_name (str): The name of the file to download
2732
2778
  run (str): The run to upload to
@@ -2779,7 +2825,7 @@ class Api:
2779
2825
  def download_file(self, url: str) -> Tuple[int, requests.Response]:
2780
2826
  """Initiate a streaming download.
2781
2827
 
2782
- Arguments:
2828
+ Args:
2783
2829
  url (str): The url to download
2784
2830
 
2785
2831
  Returns:
@@ -2813,7 +2859,7 @@ class Api:
2813
2859
  ) -> Tuple[str, Optional[requests.Response]]:
2814
2860
  """Download a file from a run and write it to wandb/.
2815
2861
 
2816
- Arguments:
2862
+ Args:
2817
2863
  metadata (obj): The metadata object for the file to download. Comes from Api.download_urls().
2818
2864
  out_dir (str, optional): The directory to write the file to. Defaults to wandb/
2819
2865
 
@@ -2877,7 +2923,7 @@ class Api:
2877
2923
  ) -> Optional[requests.Response]:
2878
2924
  """Upload a file chunk to S3 with failure resumption.
2879
2925
 
2880
- Arguments:
2926
+ Args:
2881
2927
  url: The url to download
2882
2928
  upload_chunk: The path to the file you want to upload
2883
2929
  extra_headers: A dictionary of extra headers to send with the request
@@ -2930,7 +2976,7 @@ class Api:
2930
2976
  ) -> Optional[requests.Response]:
2931
2977
  """Upload a file to W&B with failure resumption.
2932
2978
 
2933
- Arguments:
2979
+ Args:
2934
2980
  url: The url to download
2935
2981
  file: The path to the file you want to upload
2936
2982
  callback: A callback which is passed the number of
@@ -3002,7 +3048,7 @@ class Api:
3002
3048
  ) -> dict:
3003
3049
  """Register a new agent.
3004
3050
 
3005
- Arguments:
3051
+ Args:
3006
3052
  host (str): hostname
3007
3053
  sweep_id (str): sweep id
3008
3054
  project_name: (str): model that contains sweep
@@ -3052,7 +3098,7 @@ class Api:
3052
3098
  ) -> List[Dict[str, Any]]:
3053
3099
  """Notify server about agent state, receive commands.
3054
3100
 
3055
- Arguments:
3101
+ Args:
3056
3102
  agent_id (str): agent_id
3057
3103
  metrics (dict): system metrics
3058
3104
  run_states (dict): run_id: state mapping
@@ -3161,7 +3207,7 @@ class Api:
3161
3207
  ) -> Tuple[str, List[str]]:
3162
3208
  """Upsert a sweep object.
3163
3209
 
3164
- Arguments:
3210
+ Args:
3165
3211
  config (dict): sweep config (will be converted to yaml)
3166
3212
  controller (str): controller to use
3167
3213
  launch_scheduler (str): launch scheduler to use
@@ -3342,7 +3388,7 @@ class Api:
3342
3388
  ) -> "List[requests.Response]":
3343
3389
  """Download files from W&B.
3344
3390
 
3345
- Arguments:
3391
+ Args:
3346
3392
  project (str): The project to download
3347
3393
  run (str, optional): The run to upload to
3348
3394
  entity (str, optional): The entity to scope this project to. Defaults to wandb models
@@ -3377,7 +3423,7 @@ class Api:
3377
3423
  ) -> "List[Optional[requests.Response]]":
3378
3424
  """Uploads multiple files to W&B.
3379
3425
 
3380
- Arguments:
3426
+ Args:
3381
3427
  files (list or dict): The filenames to upload, when dict the values are open files
3382
3428
  run (str, optional): The run to upload to
3383
3429
  entity (str, optional): The entity to scope this project to. Defaults to wandb models
@@ -3496,7 +3542,9 @@ class Api:
3496
3542
  org_entity = ""
3497
3543
  if is_artifact_registry_project(project):
3498
3544
  try:
3499
- org_entity = self._resolve_org_entity_name(entity, organization)
3545
+ org_entity = self._resolve_org_entity_name(
3546
+ entity=entity, organization=organization
3547
+ )
3500
3548
  except ValueError as e:
3501
3549
  wandb.termerror(str(e))
3502
3550
  raise
@@ -3538,47 +3586,67 @@ class Api:
3538
3586
  # the organization parameter, or an error if it is empty. Otherwise, this returns the
3539
3587
  # fetched value after validating that the given organization, if not empty, matches
3540
3588
  # either the org's display or entity name.
3589
+
3590
+ if not entity:
3591
+ raise ValueError("Entity name is required to resolve org entity name.")
3592
+
3541
3593
  org_fields = self.server_organization_type_introspection()
3542
- can_fetch_org_entity = "orgEntity" in org_fields
3543
- if not organization and not can_fetch_org_entity:
3594
+ can_shorthand_org_entity = "orgEntity" in org_fields
3595
+ if not organization and not can_shorthand_org_entity:
3544
3596
  raise ValueError(
3545
3597
  "Fetching Registry artifacts without inputting an organization "
3546
3598
  "is unavailable for your server version. "
3547
3599
  "Please upgrade your server to 0.50.0 or later."
3548
3600
  )
3549
- if not can_fetch_org_entity:
3601
+ if not can_shorthand_org_entity:
3550
3602
  # Server doesn't support fetching org entity to validate,
3551
3603
  # assume org entity is correctly inputted
3552
3604
  return organization
3553
3605
 
3554
- org_entity, org_name = self.fetch_org_entity_from_entity(entity)
3606
+ orgs_from_entity = self._fetch_orgs_and_org_entities_from_entity(entity)
3555
3607
  if organization:
3556
- if organization != org_name and organization != org_entity:
3557
- raise ValueError(
3558
- f"Artifact belongs to the organization {org_name!r} "
3559
- f"and cannot be linked/fetched with {organization!r}. "
3560
- "Please update the target path with the correct organization name."
3561
- )
3562
- wandb.termwarn(
3563
- "Registries can be linked/fetched using a shorthand form without specifying the organization name. "
3564
- "Try using shorthand path format: <my_registry_name>/<artifact_name>"
3608
+ return _match_org_with_fetched_org_entities(organization, orgs_from_entity)
3609
+
3610
+ # If no input organization provided, error if entity belongs to multiple orgs because we
3611
+ # cannot determine which one to use.
3612
+ if len(orgs_from_entity) > 1:
3613
+ raise ValueError(
3614
+ f"Personal entity {entity!r} belongs to multiple organizations "
3615
+ "and cannot be used without specifying the organization name. "
3616
+ "Please specify the organization in the Registry path or use a team entity in the entity settings."
3565
3617
  )
3566
- return org_entity
3618
+ return orgs_from_entity[0].entity_name
3619
+
3620
+ def _fetch_orgs_and_org_entities_from_entity(self, entity: str) -> List[_OrgNames]:
3621
+ """Fetches organization entity names and display names for a given entity.
3567
3622
 
3568
- def fetch_org_entity_from_entity(self, entity: str) -> Tuple[str, str]:
3623
+ Args:
3624
+ entity (str): Entity name to lookup. Can be either a personal or team entity.
3625
+
3626
+ Returns:
3627
+ List[_OrgNames]: List of _OrgNames tuples. (_OrgNames(entity_name, display_name))
3628
+
3629
+ Raises:
3630
+ ValueError: If entity is not found, has no organizations, or other validation errors.
3631
+ """
3569
3632
  query = gql(
3570
3633
  """
3571
- query FetchOrgEntityFromEntity(
3572
- $entityName: String!,
3573
- ) {
3634
+ query FetchOrgEntityFromEntity($entityName: String!) {
3574
3635
  entity(name: $entityName) {
3575
- isTeam
3576
3636
  organization {
3577
3637
  name
3578
3638
  orgEntity {
3579
3639
  name
3580
3640
  }
3581
3641
  }
3642
+ user {
3643
+ organizations {
3644
+ name
3645
+ orgEntity {
3646
+ name
3647
+ }
3648
+ }
3649
+ }
3582
3650
  }
3583
3651
  }
3584
3652
  """
@@ -3589,28 +3657,40 @@ class Api:
3589
3657
  "entityName": entity,
3590
3658
  },
3591
3659
  )
3592
- try:
3593
- is_team = response["entity"].get("isTeam", False)
3594
- org = response["entity"]["organization"]
3595
- org_name = org["name"] or ""
3596
- org_entity_name = org["orgEntity"]["name"] or ""
3597
- except (LookupError, TypeError) as e:
3598
- if is_team:
3599
- # This path should pretty much never be reached as all team entities have an organization.
3660
+
3661
+ # Parse organization from response
3662
+ entity_resp = response["entity"]["organization"]
3663
+ user_resp = response["entity"]["user"]
3664
+ # Check for organization under team/org entity type
3665
+ if entity_resp:
3666
+ org_name = entity_resp.get("name")
3667
+ org_entity_name = entity_resp.get("orgEntity") and entity_resp[
3668
+ "orgEntity"
3669
+ ].get("name")
3670
+ if not org_name or not org_entity_name:
3600
3671
  raise ValueError(
3601
- f"Unable to find an organization under entity {entity!r}. "
3602
- ) from e
3603
- else:
3672
+ f"Unable to find an organization under entity {entity!r}."
3673
+ )
3674
+ return [_OrgNames(entity_name=org_entity_name, display_name=org_name)]
3675
+ # Check for organization under personal entity type, where a user can belong to multiple orgs
3676
+ elif user_resp:
3677
+ orgs = user_resp.get("organizations", [])
3678
+ org_entities_return = [
3679
+ _OrgNames(
3680
+ entity_name=org["orgEntity"]["name"], display_name=org["name"]
3681
+ )
3682
+ for org in orgs
3683
+ if org.get("orgEntity") and org.get("name")
3684
+ ]
3685
+ if not org_entities_return:
3604
3686
  raise ValueError(
3605
- f"Unable to resolve an organization associated with the entity: {entity!r} "
3606
- "that is initialized in the API or Run settings. This could be because "
3607
- f"{entity!r} is a personal entity or the team entity doesn't exist. "
3608
- "Please re-initialize the API or Run with a team entity using "
3609
- "wandb.Api(overrides={'entity': '<my_team_entity>'}) "
3610
- "or wandb.init(entity='<my_team_entity>') "
3611
- ) from e
3687
+ f"Unable to resolve an organization associated with personal entity: {entity!r}. "
3688
+ "This could be because its a personal entity that doesn't belong to any organizations. "
3689
+ "Please specify the organization in the Registry path or use a team entity in the entity settings."
3690
+ )
3691
+ return org_entities_return
3612
3692
  else:
3613
- return org_entity_name, org_name
3693
+ raise ValueError(f"Unable to find an organization under entity {entity!r}.")
3614
3694
 
3615
3695
  def use_artifact(
3616
3696
  self,
@@ -3701,6 +3781,41 @@ class Api:
3701
3781
 
3702
3782
  return self.server_organization_type_fields_info
3703
3783
 
3784
+ # Fetch input arguments for the "artifact" endpoint on the "Project" type
3785
+ def server_project_type_introspection(self) -> bool:
3786
+ if self.server_supports_enabling_artifact_usage_tracking is not None:
3787
+ return self.server_supports_enabling_artifact_usage_tracking
3788
+
3789
+ query_string = """
3790
+ query ProbeServerProjectInfo {
3791
+ ProjectInfoType: __type(name:"Project") {
3792
+ fields {
3793
+ name
3794
+ args {
3795
+ name
3796
+ }
3797
+ }
3798
+ }
3799
+ }
3800
+ """
3801
+
3802
+ query = gql(query_string)
3803
+ res = self.gql(query)
3804
+ input_fields = res.get("ProjectInfoType", {}).get("fields", [{}])
3805
+ artifact_args: List[Dict[str, str]] = next(
3806
+ (
3807
+ field.get("args", [])
3808
+ for field in input_fields
3809
+ if field.get("name") == "artifact"
3810
+ ),
3811
+ [],
3812
+ )
3813
+ self.server_supports_enabling_artifact_usage_tracking = any(
3814
+ arg.get("name") == "enableTracking" for arg in artifact_args
3815
+ )
3816
+
3817
+ return self.server_supports_enabling_artifact_usage_tracking
3818
+
3704
3819
  def create_artifact_type(
3705
3820
  self,
3706
3821
  artifact_type_name: str,
@@ -313,7 +313,8 @@ class JobBuilder:
313
313
  "build_context": metadata.get("build_context"),
314
314
  "dockerfile": metadata.get("dockerfile"),
315
315
  }
316
- name = self._make_job_name(self._logged_code_artifact["name"])
316
+ artifact_basename, *_ = self._logged_code_artifact["name"].split(":")
317
+ name = self._make_job_name(artifact_basename)
317
318
 
318
319
  return source, name
319
320
 
@@ -380,7 +381,7 @@ class JobBuilder:
380
381
  ]:
381
382
  """Construct a job source dict and name from the current run.
382
383
 
383
- Arguments:
384
+ Args:
384
385
  source_type (str): The type of source to build the job from. One of
385
386
  "repo", "artifact", or "image".
386
387
  """
@@ -427,7 +428,7 @@ class JobBuilder:
427
428
  ) -> Optional[Artifact]:
428
429
  """Build a job artifact from the current run.
429
430
 
430
- Arguments:
431
+ Args:
431
432
  api (Api): The API object to use to create the job artifact.
432
433
  build_context (Optional[str]): Path within the job source code to
433
434
  the image build context. Saved as part of the job for future
@@ -4,7 +4,6 @@ __all__ = (
4
4
  "Disk",
5
5
  "GPU",
6
6
  "GPUAMD",
7
- "GPUApple",
8
7
  "IPU",
9
8
  "Memory",
10
9
  "Network",
@@ -18,7 +17,6 @@ from .cpu import CPU
18
17
  from .disk import Disk
19
18
  from .gpu import GPU
20
19
  from .gpu_amd import GPUAMD
21
- from .gpu_apple import GPUApple
22
20
  from .ipu import IPU
23
21
  from .memory import Memory
24
22
  from .network import Network
@@ -12,7 +12,7 @@ from typing import TYPE_CHECKING, Any, Dict, List, Optional
12
12
 
13
13
  import wandb
14
14
  from wandb import util
15
- from wandb.plot.viz import CustomChart
15
+ from wandb.plot import CustomChart
16
16
  from wandb.sdk.interface.interface import GlobStr
17
17
  from wandb.sdk.lib import filesystem
18
18
 
@@ -73,7 +73,7 @@ def is_tfevents_file_created_by(
73
73
  if not path:
74
74
  raise ValueError("Path must be a nonempty string")
75
75
  basename = os.path.basename(path)
76
- if basename.endswith(".profile-empty") or basename.endswith(".sagemaker-uploaded"):
76
+ if basename.endswith((".profile-empty", ".sagemaker-uploaded")):
77
77
  return False
78
78
  fname_components = basename.split(".")
79
79
  try:
@@ -439,18 +439,19 @@ class TBEventConsumer:
439
439
 
440
440
  def _save_row(self, row: "HistoryDict") -> None:
441
441
  chart_keys = set()
442
- for k in row:
443
- if isinstance(row[k], CustomChart):
442
+ for k, v in row.items():
443
+ if isinstance(v, CustomChart):
444
444
  chart_keys.add(k)
445
- key = row[k].get_config_key(k)
446
- value = row[k].get_config_value(
447
- "Vega2", row[k].user_query(f"{k}_table")
445
+ v.set_key(k)
446
+ self._tbwatcher._interface.publish_config(
447
+ key=v.spec.config_key,
448
+ val=v.spec.config_value,
448
449
  )
449
- row[k] = row[k]._data
450
- self._tbwatcher._interface.publish_config(val=value, key=key)
451
450
 
452
451
  for k in chart_keys:
453
- row[f"{k}_table"] = row.pop(k)
452
+ chart = row.pop(k)
453
+ if isinstance(chart, CustomChart):
454
+ row[chart.spec.table_key] = chart.table
454
455
 
455
456
  self._tbwatcher._interface.publish_history(
456
457
  row, run=self._internal_run, publish_step=False
@@ -120,10 +120,11 @@ def resolve_agent_config( # noqa: C901
120
120
  if isinstance(resolved_config.get("queue"), str):
121
121
  resolved_config["queues"].append(resolved_config["queue"])
122
122
  else:
123
- raise LaunchError(
124
- f"Invalid launch agent config for key 'queue' with type: {type(resolved_config.get('queue'))}"
125
- + " (expected str). Specify multiple queues with the 'queues' key"
123
+ msg = (
124
+ "Invalid launch agent config for key 'queue' with type: {type(resolved_config.get('queue'))} "
125
+ "(expected str). Specify multiple queues with the 'queues' key"
126
126
  )
127
+ raise LaunchError(msg)
127
128
 
128
129
  keys = ["entity"]
129
130
  settings = {
@@ -61,7 +61,7 @@ def launch_add(
61
61
  config: A dictionary containing the configuration for the run. May also contain
62
62
  resource specific arguments under the key "resource_args"
63
63
  template_variables: A dictionary containing values of template variables for a run queue.
64
- Expected format of {"VAR_NAME": VAR_VALUE}
64
+ Expected format of `{"VAR_NAME": VAR_VALUE}`
65
65
  project: Target project to send launched run to
66
66
  entity: Target entity to send launched run to
67
67
  queue: the name of the queue to enqueue the run to
@@ -240,7 +240,7 @@ def _launch_add(
240
240
  public_api = public.Api()
241
241
  if job is not None:
242
242
  try:
243
- public_api.artifact(job, type="job")
243
+ public_api._artifact(job, type="job")
244
244
  except (ValueError, CommError) as e:
245
245
  raise LaunchError(f"Unable to fetch job with name {job}: {e}")
246
246
 
@@ -199,7 +199,6 @@ class KanikoBuilder(AbstractBuilder):
199
199
 
200
200
  def login(self) -> None:
201
201
  """Login to the registry."""
202
- pass
203
202
 
204
203
  async def _create_docker_ecr_config_map(
205
204
  self, job_name: str, corev1_client: client.CoreV1Api, repository: str
@@ -168,6 +168,7 @@ def _create_job(
168
168
  return None, "", []
169
169
 
170
170
  job_builder = _configure_job_builder_for_partial(tempdir.name, job_source=job_type)
171
+ job_builder._settings.update(job_name=name)
171
172
  if job_type == "code":
172
173
  assert entrypoint is not None
173
174
  job_name = _make_code_artifact(
@@ -12,7 +12,6 @@ class LocalEnvironment(AbstractEnvironment):
12
12
 
13
13
  def __init__(self) -> None:
14
14
  """Initialize a local environment by doing nothing."""
15
- pass
16
15
 
17
16
  @classmethod
18
17
  def from_config(
@@ -4,16 +4,10 @@ from wandb.errors import Error
4
4
  class LaunchError(Error):
5
5
  """Raised when a known error occurs in wandb launch."""
6
6
 
7
- pass
8
-
9
7
 
10
8
  class LaunchDockerError(Error):
11
9
  """Raised when Docker daemon is not running."""
12
10
 
13
- pass
14
-
15
11
 
16
12
  class ExecutionError(Error):
17
13
  """Generic execution exception."""
18
-
19
- pass
@@ -20,7 +20,6 @@ class LocalRegistry(AbstractRegistry):
20
20
 
21
21
  def __init__(self) -> None:
22
22
  """Initialize a local registry."""
23
- pass
24
23
 
25
24
  @classmethod
26
25
  def from_config(
@@ -40,7 +39,6 @@ class LocalRegistry(AbstractRegistry):
40
39
 
41
40
  async def verify(self) -> None:
42
41
  """Verify the local registry by doing nothing."""
43
- pass
44
42
 
45
43
  async def get_username_password(self) -> Tuple[str, str]:
46
44
  """Get the username and password of the local registry."""