wandb 0.18.2__py3-none-macosx_10_13_x86_64.whl → 0.18.4__py3-none-macosx_10_13_x86_64.whl

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. wandb/__init__.py +16 -7
  2. wandb/__init__.pyi +96 -63
  3. wandb/analytics/sentry.py +91 -88
  4. wandb/apis/public/api.py +18 -4
  5. wandb/apis/public/runs.py +53 -2
  6. wandb/bin/gpu_stats +0 -0
  7. wandb/bin/wandb-core +0 -0
  8. wandb/cli/beta.py +178 -0
  9. wandb/cli/cli.py +5 -171
  10. wandb/data_types.py +3 -0
  11. wandb/env.py +74 -73
  12. wandb/errors/term.py +300 -43
  13. wandb/proto/v3/wandb_internal_pb2.py +271 -221
  14. wandb/proto/v3/wandb_server_pb2.py +57 -37
  15. wandb/proto/v3/wandb_settings_pb2.py +2 -2
  16. wandb/proto/v4/wandb_internal_pb2.py +226 -216
  17. wandb/proto/v4/wandb_server_pb2.py +41 -37
  18. wandb/proto/v4/wandb_settings_pb2.py +2 -2
  19. wandb/proto/v5/wandb_internal_pb2.py +226 -216
  20. wandb/proto/v5/wandb_server_pb2.py +41 -37
  21. wandb/proto/v5/wandb_settings_pb2.py +2 -2
  22. wandb/sdk/__init__.py +3 -3
  23. wandb/sdk/artifacts/_validators.py +41 -8
  24. wandb/sdk/artifacts/artifact.py +35 -4
  25. wandb/sdk/artifacts/artifact_file_cache.py +1 -2
  26. wandb/sdk/data_types/_dtypes.py +7 -3
  27. wandb/sdk/data_types/video.py +15 -6
  28. wandb/sdk/interface/interface.py +2 -0
  29. wandb/sdk/internal/internal_api.py +122 -5
  30. wandb/sdk/internal/sender.py +16 -3
  31. wandb/sdk/launch/inputs/internal.py +1 -1
  32. wandb/sdk/lib/module.py +12 -0
  33. wandb/sdk/lib/printer.py +291 -105
  34. wandb/sdk/lib/progress.py +274 -0
  35. wandb/sdk/service/streams.py +21 -11
  36. wandb/sdk/wandb_init.py +59 -54
  37. wandb/sdk/wandb_run.py +413 -480
  38. wandb/sdk/wandb_settings.py +2 -0
  39. wandb/sdk/wandb_watch.py +17 -11
  40. wandb/util.py +6 -2
  41. {wandb-0.18.2.dist-info → wandb-0.18.4.dist-info}/METADATA +5 -4
  42. {wandb-0.18.2.dist-info → wandb-0.18.4.dist-info}/RECORD +45 -42
  43. {wandb-0.18.2.dist-info → wandb-0.18.4.dist-info}/WHEEL +0 -0
  44. {wandb-0.18.2.dist-info → wandb-0.18.4.dist-info}/entry_points.txt +0 -0
  45. {wandb-0.18.2.dist-info → wandb-0.18.4.dist-info}/licenses/LICENSE +0 -0
wandb/__init__.py CHANGED
@@ -8,9 +8,10 @@ For scripts and interactive notebooks, see https://github.com/wandb/examples.
8
8
 
9
9
  For reference documentation, see https://docs.wandb.com/ref/python.
10
10
  """
11
- __version__ = "0.18.2"
11
+ from __future__ import annotations
12
+
13
+ __version__ = "0.18.4"
12
14
 
13
- from typing import Optional
14
15
 
15
16
  from wandb.errors import Error
16
17
 
@@ -28,8 +29,6 @@ setup = wandb_sdk.setup
28
29
  _attach = wandb_sdk._attach
29
30
  _sync = wandb_sdk._sync
30
31
  _teardown = wandb_sdk.teardown
31
- watch = wandb_sdk.watch
32
- unwatch = wandb_sdk.unwatch
33
32
  finish = wandb_sdk.finish
34
33
  join = finish
35
34
  login = wandb_sdk.login
@@ -112,10 +111,12 @@ def _assert_is_user_process():
112
111
  # globals
113
112
  Api = PublicApi
114
113
  api = InternalApi()
115
- run: Optional["wandb_sdk.wandb_run.Run"] = None
114
+ run: wandb_sdk.wandb_run.Run | None = None
116
115
  config = _preinit.PreInitObject("wandb.config", wandb_sdk.wandb_config.Config)
117
116
  summary = _preinit.PreInitObject("wandb.summary", wandb_sdk.wandb_summary.Summary)
118
117
  log = _preinit.PreInitCallable("wandb.log", wandb_sdk.wandb_run.Run.log) # type: ignore
118
+ watch = _preinit.PreInitCallable("wandb.watch", wandb_sdk.wandb_run.Run.watch) # type: ignore
119
+ unwatch = _preinit.PreInitCallable("wandb.unwatch", wandb_sdk.wandb_run.Run.unwatch) # type: ignore
119
120
  save = _preinit.PreInitCallable("wandb.save", wandb_sdk.wandb_run.Run.save) # type: ignore
120
121
  restore = wandb_sdk.wandb_run.restore
121
122
  use_artifact = _preinit.PreInitCallable(
@@ -200,9 +201,16 @@ if "dev" in __version__:
200
201
  import wandb.env
201
202
  import os
202
203
 
203
- # disable error reporting in dev versions for the python client
204
+ # Disable error reporting in dev versions.
204
205
  os.environ[wandb.env.ERROR_REPORTING] = os.environ.get(
205
- wandb.env.ERROR_REPORTING, "false"
206
+ wandb.env.ERROR_REPORTING,
207
+ "false",
208
+ )
209
+
210
+ # Enable new features in dev versions.
211
+ os.environ["WANDB__SHOW_OPERATION_STATS"] = os.environ.get(
212
+ "WANDB__SHOW_OPERATION_STATS",
213
+ "true",
206
214
  )
207
215
 
208
216
  _sentry = _Sentry()
@@ -242,4 +250,5 @@ __all__ = (
242
250
  "link_model",
243
251
  "define_metric",
244
252
  "watch",
253
+ "unwatch",
245
254
  )
wandb/__init__.pyi CHANGED
@@ -52,6 +52,7 @@ __all__ = (
52
52
  "Settings",
53
53
  "teardown",
54
54
  "watch",
55
+ "unwatch",
55
56
  )
56
57
 
57
58
  import os
@@ -95,12 +96,14 @@ from wandb.wandb_controller import _WandbController
95
96
  if TYPE_CHECKING:
96
97
  import torch # type: ignore [import-not-found]
97
98
 
98
- __version__: str = "0.18.2"
99
+ from wandb.plot.viz import CustomChart
100
+
101
+ __version__: str = "0.18.4"
99
102
 
100
103
  run: Run | None
101
104
  config: wandb_config.Config
102
105
  summary: wandb_summary.Summary
103
- Api: PublicApi
106
+ Api: type[PublicApi]
104
107
 
105
108
  # private attributes
106
109
  _sentry: Sentry
@@ -181,32 +184,32 @@ def teardown(exit_code: Optional[int] = None) -> None:
181
184
  ...
182
185
 
183
186
  def init(
184
- job_type: Optional[str] = None,
185
- dir: Optional[StrPath] = None,
186
- config: Union[Dict, str, None] = None,
187
- project: Optional[str] = None,
188
- entity: Optional[str] = None,
189
- reinit: Optional[bool] = None,
190
- tags: Optional[Sequence] = None,
191
- group: Optional[str] = None,
192
- name: Optional[str] = None,
193
- notes: Optional[str] = None,
194
- magic: Optional[Union[dict, str, bool]] = None,
195
- config_exclude_keys: Optional[List[str]] = None,
196
- config_include_keys: Optional[List[str]] = None,
197
- anonymous: Optional[str] = None,
198
- mode: Optional[str] = None,
199
- allow_val_change: Optional[bool] = None,
200
- resume: Optional[Union[bool, str]] = None,
201
- force: Optional[bool] = None,
202
- tensorboard: Optional[bool] = None,
203
- sync_tensorboard: Optional[bool] = None,
204
- monitor_gym: Optional[bool] = None,
205
- save_code: Optional[bool] = None,
206
- id: Optional[str] = None,
207
- fork_from: Optional[str] = None,
208
- resume_from: Optional[str] = None,
209
- settings: Union[Settings, Dict[str, Any], None] = None,
187
+ job_type: str | None = None,
188
+ dir: StrPath | None = None,
189
+ config: dict | str | None = None,
190
+ project: str | None = None,
191
+ entity: str | None = None,
192
+ reinit: bool | None = None,
193
+ tags: Sequence | None = None,
194
+ group: str | None = None,
195
+ name: str | None = None,
196
+ notes: str | None = None,
197
+ magic: dict | str | bool | None = None,
198
+ config_exclude_keys: list[str] | None = None,
199
+ config_include_keys: list[str] | None = None,
200
+ anonymous: str | None = None,
201
+ mode: str | None = None,
202
+ allow_val_change: bool | None = None,
203
+ resume: bool | str | None = None,
204
+ force: bool | None = None,
205
+ tensorboard: bool | None = None, # alias for sync_tensorboard
206
+ sync_tensorboard: bool | None = None,
207
+ monitor_gym: bool | None = None,
208
+ save_code: bool | None = None,
209
+ id: str | None = None,
210
+ fork_from: str | None = None,
211
+ resume_from: str | None = None,
212
+ settings: Settings | dict[str, Any] | None = None,
210
213
  ) -> Run:
211
214
  r"""Start a new run to track and log to W&B.
212
215
 
@@ -420,7 +423,7 @@ def init(
420
423
  """
421
424
  ...
422
425
 
423
- def finish(exit_code: Optional[int] = None, quiet: Optional[bool] = None) -> None:
426
+ def finish(exit_code: int | None = None, quiet: bool | None = None) -> None:
424
427
  """Mark a run as finished, and finish uploading all data.
425
428
 
426
429
  This is used when creating multiple runs in the same process.
@@ -470,10 +473,10 @@ def login(
470
473
  ...
471
474
 
472
475
  def log(
473
- data: Dict[str, Any],
474
- step: Optional[int] = None,
475
- commit: Optional[bool] = None,
476
- sync: Optional[bool] = None,
476
+ data: dict[str, Any],
477
+ step: int | None = None,
478
+ commit: bool | None = None,
479
+ sync: bool | None = None,
477
480
  ) -> None:
478
481
  """Upload run data.
479
482
 
@@ -704,10 +707,10 @@ def log(
704
707
  ...
705
708
 
706
709
  def save(
707
- glob_str: Optional[Union[str, os.PathLike]] = None,
708
- base_path: Optional[Union[str, os.PathLike]] = None,
710
+ glob_str: str | os.PathLike | None = None,
711
+ base_path: str | os.PathLike | None = None,
709
712
  policy: PolicyName = "live",
710
- ) -> Union[bool, List[str]]:
713
+ ) -> bool | list[str]:
711
714
  """Sync one or more files to W&B.
712
715
 
713
716
  Relative paths are relative to the current working directory.
@@ -846,12 +849,12 @@ def agent(
846
849
 
847
850
  def define_metric(
848
851
  name: str,
849
- step_metric: Union[str, wandb_metric.Metric, None] = None,
850
- step_sync: Optional[bool] = None,
851
- hidden: Optional[bool] = None,
852
- summary: Optional[str] = None,
853
- goal: Optional[str] = None,
854
- overwrite: Optional[bool] = None,
852
+ step_metric: str | wandb_metric.Metric | None = None,
853
+ step_sync: bool | None = None,
854
+ hidden: bool | None = None,
855
+ summary: str | None = None,
856
+ goal: str | None = None,
857
+ overwrite: bool | None = None,
855
858
  ) -> wandb_metric.Metric:
856
859
  """Customize metrics logged with `wandb.log()`.
857
860
 
@@ -882,11 +885,11 @@ def define_metric(
882
885
  ...
883
886
 
884
887
  def log_artifact(
885
- artifact_or_path: Union[Artifact, StrPath],
886
- name: Optional[str] = None,
887
- type: Optional[str] = None,
888
- aliases: Optional[List[str]] = None,
889
- tags: Optional[List[str]] = None,
888
+ artifact_or_path: Artifact | StrPath,
889
+ name: str | None = None,
890
+ type: str | None = None,
891
+ aliases: list[str] | None = None,
892
+ tags: list[str] | None = None,
890
893
  ) -> Artifact:
891
894
  """Declare an artifact as an output of a run.
892
895
 
@@ -915,10 +918,10 @@ def log_artifact(
915
918
  ...
916
919
 
917
920
  def use_artifact(
918
- artifact_or_name: Union[str, Artifact],
919
- type: Optional[str] = None,
920
- aliases: Optional[List[str]] = None,
921
- use_as: Optional[str] = None,
921
+ artifact_or_name: str | Artifact,
922
+ type: str | None = None,
923
+ aliases: list[str] | None = None,
924
+ use_as: str | None = None,
922
925
  ) -> Artifact:
923
926
  """Declare an artifact as an input to a run.
924
927
 
@@ -926,8 +929,9 @@ def use_artifact(
926
929
 
927
930
  Arguments:
928
931
  artifact_or_name: (str or Artifact) An artifact name.
929
- May be prefixed with entity/project/. Valid names
930
- can be in the following forms:
932
+ May be prefixed with project/ or entity/project/.
933
+ If no entity is specified in the name, the Run or API setting's entity is used.
934
+ Valid names can be in the following forms:
931
935
  - name:version
932
936
  - name:alias
933
937
  You can also pass an Artifact object created by calling `wandb.Artifact`
@@ -943,8 +947,8 @@ def use_artifact(
943
947
 
944
948
  def log_model(
945
949
  path: StrPath,
946
- name: Optional[str] = None,
947
- aliases: Optional[List[str]] = None,
950
+ name: str | None = None,
951
+ aliases: list[str] | None = None,
948
952
  ) -> None:
949
953
  """Logs a model artifact containing the contents inside the 'path' to a run and marks it as an output to this run.
950
954
 
@@ -1031,8 +1035,8 @@ def use_model(name: str) -> FilePathStr:
1031
1035
  def link_model(
1032
1036
  path: StrPath,
1033
1037
  registered_model_name: str,
1034
- name: Optional[str] = None,
1035
- aliases: Optional[List[str]] = None,
1038
+ name: str | None = None,
1039
+ aliases: list[str] | None = None,
1036
1040
  ) -> None:
1037
1041
  """Log a model artifact version and link it to a registered model in the model registry.
1038
1042
 
@@ -1099,6 +1103,28 @@ def link_model(
1099
1103
  """
1100
1104
  ...
1101
1105
 
1106
+ def plot_table(
1107
+ vega_spec_name: str,
1108
+ data_table: Table,
1109
+ fields: dict[str, Any],
1110
+ string_fields: dict[str, Any] | None = None,
1111
+ split_table: bool | None = False,
1112
+ ) -> CustomChart:
1113
+ """Create a custom plot on a table.
1114
+
1115
+ Arguments:
1116
+ vega_spec_name: the name of the spec for the plot
1117
+ data_table: a wandb.Table object containing the data to
1118
+ be used on the visualization
1119
+ fields: a dict mapping from table keys to fields that the custom
1120
+ visualization needs
1121
+ string_fields: a dict that provides values for any string constants
1122
+ the custom visualization needs
1123
+ split_table: a boolean that indicates whether the table should be in
1124
+ a separate section in the UI
1125
+ """
1126
+ ...
1127
+
1102
1128
  def watch(
1103
1129
  models: torch.nn.Module | Sequence[torch.nn.Module],
1104
1130
  criterion: torch.F | None = None,
@@ -1106,7 +1132,7 @@ def watch(
1106
1132
  log_freq: int = 1000,
1107
1133
  idx: int | None = None,
1108
1134
  log_graph: bool = False,
1109
- ) -> Graph:
1135
+ ) -> None:
1110
1136
  """Hooks into the given PyTorch model(s) to monitor gradients and the model's computational graph.
1111
1137
 
1112
1138
  This function can track parameters, gradients, or both during training. It should be
@@ -1124,16 +1150,23 @@ def watch(
1124
1150
  Frequency (in batches) to log gradients and parameters. (default=1000)
1125
1151
  idx (Optional[int]):
1126
1152
  Index used when tracking multiple models with `wandb.watch`. (default=None)
1127
- log_graph (bool):
1153
+ log_graph (bool):
1128
1154
  Whether to log the model's computational graph. (default=False)
1129
1155
 
1130
- Returns:
1131
- wandb.Graph:
1132
- The graph object, which will be populated after the first backward pass.
1133
-
1134
1156
  Raises:
1135
1157
  ValueError:
1136
1158
  If `wandb.init` has not been called or if any of the models are not instances
1137
1159
  of `torch.nn.Module`.
1138
1160
  """
1139
1161
  ...
1162
+
1163
+ def unwatch(
1164
+ models: torch.nn.Module | Sequence[torch.nn.Module] | None = None,
1165
+ ) -> None:
1166
+ """Remove pytorch model topology, gradient and parameter hooks.
1167
+
1168
+ Args:
1169
+ models (torch.nn.Module | Sequence[torch.nn.Module]):
1170
+ Optional list of pytorch models that have had watch called on them
1171
+ """
1172
+ ...
wandb/analytics/sentry.py CHANGED
@@ -1,3 +1,5 @@
1
+ from __future__ import annotations
2
+
1
3
  __all__ = ("Sentry",)
2
4
 
3
5
 
@@ -7,7 +9,7 @@ import os
7
9
  import pathlib
8
10
  import sys
9
11
  from types import TracebackType
10
- from typing import TYPE_CHECKING, Any, Callable, Dict, Optional, Tuple, Type, Union
12
+ from typing import TYPE_CHECKING, Any, Callable
11
13
  from urllib.parse import quote
12
14
 
13
15
  if sys.version_info >= (3, 8):
@@ -16,6 +18,7 @@ else:
16
18
  from typing_extensions import Literal
17
19
 
18
20
  import sentry_sdk # type: ignore
21
+ import sentry_sdk.scope # type: ignore
19
22
  import sentry_sdk.utils # type: ignore
20
23
 
21
24
  import wandb
@@ -36,7 +39,7 @@ def _safe_noop(func: Callable) -> Callable:
36
39
  """Decorator to ensure that Sentry methods do nothing if disabled and don't raise."""
37
40
 
38
41
  @functools.wraps(func)
39
- def wrapper(self: Type["Sentry"], *args: Any, **kwargs: Any) -> Any:
42
+ def wrapper(self: type[Sentry], *args: Any, **kwargs: Any) -> Any:
40
43
  if self._disabled:
41
44
  return None
42
45
  try:
@@ -59,7 +62,7 @@ class Sentry:
59
62
 
60
63
  self.dsn = os.environ.get(wandb.env.SENTRY_DSN, SENTRY_DEFAULT_DSN)
61
64
 
62
- self.hub: Optional[sentry_sdk.hub.Hub] = None
65
+ self.scope: sentry_sdk.scope.Scope | None = None
63
66
 
64
67
  # ensure we always end the Sentry session
65
68
  atexit.register(self.end_session)
@@ -87,47 +90,50 @@ class Sentry:
87
90
  environment=self.environment,
88
91
  release=wandb.__version__,
89
92
  )
90
- self.hub = sentry_sdk.Hub(client)
93
+ self.scope = sentry_sdk.get_global_scope().fork()
94
+ self.scope.clear()
95
+ self.scope.set_client(client)
91
96
 
92
97
  @_safe_noop
93
- def message(self, message: str, repeat: bool = True) -> None:
98
+ def message(self, message: str, repeat: bool = True) -> str | None:
94
99
  """Send a message to Sentry."""
95
100
  if not repeat and message in self._sent_messages:
96
- return
101
+ return None
97
102
  self._sent_messages.add(message)
98
- self.hub.capture_message(message) # type: ignore
103
+ with sentry_sdk.scope.use_isolation_scope(self.scope): # type: ignore
104
+ return sentry_sdk.capture_message(message) # type: ignore
99
105
 
100
106
  @_safe_noop
101
107
  def exception(
102
108
  self,
103
- exc: Union[
104
- str,
105
- BaseException,
106
- Tuple[
107
- Optional[Type[BaseException]],
108
- Optional[BaseException],
109
- Optional[TracebackType],
110
- ],
111
- None,
112
- ],
109
+ exc: str
110
+ | BaseException
111
+ | tuple[
112
+ type[BaseException] | None,
113
+ BaseException | None,
114
+ TracebackType | None,
115
+ ]
116
+ | None,
113
117
  handled: bool = False,
114
- status: Optional["SessionStatus"] = None,
115
- ) -> None:
118
+ status: SessionStatus | None = None,
119
+ ) -> str | None:
116
120
  """Log an exception to Sentry."""
117
- error = Exception(exc) if isinstance(exc, str) else exc
118
- # based on self.hub.capture_exception(_exc)
119
- if error is not None:
120
- exc_info = sentry_sdk.utils.exc_info_from_error(error)
121
+ if isinstance(exc, str):
122
+ exc_info = sentry_sdk.utils.exc_info_from_error(Exception(exc))
123
+ elif isinstance(exc, BaseException):
124
+ exc_info = sentry_sdk.utils.exc_info_from_error(exc)
121
125
  else:
122
126
  exc_info = sys.exc_info()
123
127
 
124
- event, hint = sentry_sdk.utils.event_from_exception(
128
+ event, _ = sentry_sdk.utils.event_from_exception(
125
129
  exc_info,
126
- client_options=self.hub.client.options, # type: ignore
130
+ client_options=self.scope.get_client().options, # type: ignore
127
131
  mechanism={"type": "generic", "handled": handled},
128
132
  )
133
+ event_id = None
129
134
  try:
130
- self.hub.capture_event(event, hint=hint) # type: ignore
135
+ with sentry_sdk.scope.use_isolation_scope(self.scope): # type: ignore
136
+ event_id = sentry_sdk.capture_event(event) # type: ignore
131
137
  except Exception:
132
138
  pass
133
139
 
@@ -136,11 +142,11 @@ class Sentry:
136
142
  status = status or ("crashed" if not handled else "errored") # type: ignore
137
143
  self.mark_session(status=status)
138
144
 
139
- client, _ = self.hub._stack[-1] # type: ignore
145
+ client = self.scope.get_client() # type: ignore
140
146
  if client is not None:
141
147
  client.flush()
142
148
 
143
- return None
149
+ return event_id
144
150
 
145
151
  def reraise(self, exc: Any) -> None:
146
152
  """Re-raise an exception after logging it to Sentry.
@@ -157,33 +163,31 @@ class Sentry:
157
163
  @_safe_noop
158
164
  def start_session(self) -> None:
159
165
  """Start a new session."""
160
- assert self.hub is not None
166
+ assert self.scope is not None
161
167
  # get the current client and scope
162
- _, scope = self.hub._stack[-1]
163
- session = scope._session
168
+ session = self.scope._session
164
169
 
165
170
  # if there's no session, start one
166
171
  if session is None:
167
- self.hub.start_session()
172
+ self.scope.start_session()
168
173
 
169
174
  @_safe_noop
170
175
  def end_session(self) -> None:
171
176
  """End the current session."""
172
- assert self.hub is not None
177
+ assert self.scope is not None
173
178
  # get the current client and scope
174
- client, scope = self.hub._stack[-1]
175
- session = scope._session
179
+ client = self.scope.get_client()
180
+ session = self.scope._session
176
181
 
177
182
  if session is not None and client is not None:
178
- self.hub.end_session()
183
+ self.scope.end_session()
179
184
  client.flush()
180
185
 
181
186
  @_safe_noop
182
- def mark_session(self, status: Optional["SessionStatus"] = None) -> None:
187
+ def mark_session(self, status: SessionStatus | None = None) -> None:
183
188
  """Mark the current session with a status."""
184
- assert self.hub is not None
185
- _, scope = self.hub._stack[-1]
186
- session = scope._session
189
+ assert self.scope is not None
190
+ session = self.scope._session
187
191
 
188
192
  if session is not None:
189
193
  session.update(status=status)
@@ -191,8 +195,8 @@ class Sentry:
191
195
  @_safe_noop
192
196
  def configure_scope(
193
197
  self,
194
- tags: Optional[Dict[str, Any]] = None,
195
- process_context: Optional[str] = None,
198
+ tags: dict[str, Any] | None = None,
199
+ process_context: str | None = None,
196
200
  ) -> None:
197
201
  """Configure the Sentry scope for the current thread.
198
202
 
@@ -201,7 +205,7 @@ class Sentry:
201
205
  all events sent from this thread. It also tries to start a session
202
206
  if one doesn't already exist for this thread.
203
207
  """
204
- assert self.hub is not None
208
+ assert self.scope is not None
205
209
  settings_tags = (
206
210
  "entity",
207
211
  "project",
@@ -215,51 +219,50 @@ class Sentry:
215
219
  "launch",
216
220
  )
217
221
 
218
- with self.hub.configure_scope() as scope:
219
- scope.set_tag("platform", wandb.util.get_platform_name())
220
-
221
- # set context
222
- if process_context:
223
- scope.set_tag("process_context", process_context)
224
-
225
- # apply settings tags
226
- if tags is None:
227
- return None
228
-
229
- for tag in settings_tags:
230
- val = tags.get(tag, None)
231
- if val not in (None, ""):
232
- scope.set_tag(tag, val)
233
-
234
- if tags.get("_colab", None):
235
- python_runtime = "colab"
236
- elif tags.get("_jupyter", None):
237
- python_runtime = "jupyter"
238
- elif tags.get("_ipython", None):
239
- python_runtime = "ipython"
240
- else:
241
- python_runtime = "python"
242
- scope.set_tag("python_runtime", python_runtime)
243
-
244
- # Construct run_url and sweep_url given run_id and sweep_id
245
- for obj in ("run", "sweep"):
246
- obj_id, obj_url = f"{obj}_id", f"{obj}_url"
247
- if tags.get(obj_url, None):
248
- continue
249
-
250
- try:
251
- app_url = wandb.util.app_url(tags["base_url"]) # type: ignore
252
- entity, project = (quote(tags[k]) for k in ("entity", "project")) # type: ignore
253
- scope.set_tag(
254
- obj_url,
255
- f"{app_url}/{entity}/{project}/{obj}s/{tags[obj_id]}",
256
- )
257
- except Exception:
258
- pass
259
-
260
- email = tags.get("email")
261
- if email:
262
- scope.user = {"email": email} # noqa
222
+ self.scope.set_tag("platform", wandb.util.get_platform_name())
223
+
224
+ # set context
225
+ if process_context:
226
+ self.scope.set_tag("process_context", process_context)
227
+
228
+ # apply settings tags
229
+ if tags is None:
230
+ return None
231
+
232
+ for tag in settings_tags:
233
+ val = tags.get(tag, None)
234
+ if val not in (None, ""):
235
+ self.scope.set_tag(tag, val)
236
+
237
+ if tags.get("_colab", None):
238
+ python_runtime = "colab"
239
+ elif tags.get("_jupyter", None):
240
+ python_runtime = "jupyter"
241
+ elif tags.get("_ipython", None):
242
+ python_runtime = "ipython"
243
+ else:
244
+ python_runtime = "python"
245
+ self.scope.set_tag("python_runtime", python_runtime)
246
+
247
+ # Construct run_url and sweep_url given run_id and sweep_id
248
+ for obj in ("run", "sweep"):
249
+ obj_id, obj_url = f"{obj}_id", f"{obj}_url"
250
+ if tags.get(obj_url, None):
251
+ continue
252
+
253
+ try:
254
+ app_url = wandb.util.app_url(tags["base_url"]) # type: ignore
255
+ entity, project = (quote(tags[k]) for k in ("entity", "project")) # type: ignore
256
+ self.scope.set_tag(
257
+ obj_url,
258
+ f"{app_url}/{entity}/{project}/{obj}s/{tags[obj_id]}",
259
+ )
260
+ except Exception:
261
+ pass
262
+
263
+ email = tags.get("email")
264
+ if email:
265
+ self.scope.user = {"email": email} # noqa
263
266
 
264
267
  # todo: add back the option to pass general tags see: c645f625d1c1a3db4a6b0e2aa8e924fee101904c (wandb/util.py)
265
268
 
wandb/apis/public/api.py CHANGED
@@ -27,6 +27,7 @@ from wandb.apis import public
27
27
  from wandb.apis.internal import Api as InternalApi
28
28
  from wandb.apis.normalize import normalize_exceptions
29
29
  from wandb.apis.public.const import RETRY_TIMEDELTA
30
+ from wandb.sdk.artifacts._validators import is_artifact_registry_project
30
31
  from wandb.sdk.internal.thread_local_settings import _thread_local_api_settings
31
32
  from wandb.sdk.launch.utils import LAUNCH_DEFAULT_PROJECT
32
33
  from wandb.sdk.lib import retry, runid
@@ -1142,11 +1143,12 @@ class Api:
1142
1143
 
1143
1144
  @normalize_exceptions
1144
1145
  def artifact(self, name, type=None):
1145
- """Return a single artifact by parsing path in the form `entity/project/name`.
1146
+ """Return a single artifact by parsing path in the form `project/name` or `entity/project/name`.
1146
1147
 
1147
1148
  Arguments:
1148
- name: (str) An artifact name. May be prefixed with entity/project. Valid names
1149
- can be in the following forms:
1149
+ name: (str) An artifact name. May be prefixed with project/ or entity/project/.
1150
+ If no entity is specified in the name, the Run or API setting's entity is used.
1151
+ Valid names can be in the following forms:
1150
1152
  name:version
1151
1153
  name:alias
1152
1154
  type: (str, optional) The type of artifact to fetch.
@@ -1157,8 +1159,20 @@ class Api:
1157
1159
  if name is None:
1158
1160
  raise ValueError("You must specify name= to fetch an artifact.")
1159
1161
  entity, project, artifact_name = self._parse_artifact_path(name)
1162
+
1163
+ organization = ""
1164
+ # If its an Registry artifact, the entity is an org instead
1165
+ if is_artifact_registry_project(project):
1166
+ # Update `organization` only if an organization name was provided,
1167
+ # otherwise use the default that you already set above.
1168
+ try:
1169
+ organization, _, _ = name.split("/")
1170
+ except ValueError:
1171
+ organization = ""
1172
+ # set entity to match the settings since in above code it was potentially set to an org
1173
+ entity = self.settings["entity"] or self.default_entity
1160
1174
  artifact = wandb.Artifact._from_name(
1161
- entity, project, artifact_name, self.client
1175
+ entity, project, artifact_name, self.client, organization
1162
1176
  )
1163
1177
  if type is not None and artifact.type != type:
1164
1178
  raise ValueError(