wandb 0.21.0__py3-none-macosx_11_0_arm64.whl → 0.21.1__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.
Files changed (97) hide show
  1. wandb/__init__.py +16 -14
  2. wandb/__init__.pyi +427 -450
  3. wandb/agents/pyagent.py +41 -12
  4. wandb/analytics/sentry.py +7 -2
  5. wandb/apis/importers/mlflow.py +1 -1
  6. wandb/apis/public/__init__.py +1 -1
  7. wandb/apis/public/api.py +526 -360
  8. wandb/apis/public/artifacts.py +204 -8
  9. wandb/apis/public/automations.py +19 -3
  10. wandb/apis/public/files.py +172 -33
  11. wandb/apis/public/history.py +67 -15
  12. wandb/apis/public/integrations.py +25 -2
  13. wandb/apis/public/jobs.py +90 -2
  14. wandb/apis/public/projects.py +130 -79
  15. wandb/apis/public/query_generator.py +11 -1
  16. wandb/apis/public/registries/registries_search.py +7 -15
  17. wandb/apis/public/reports.py +83 -5
  18. wandb/apis/public/runs.py +299 -105
  19. wandb/apis/public/sweeps.py +222 -22
  20. wandb/apis/public/teams.py +41 -4
  21. wandb/apis/public/users.py +45 -4
  22. wandb/beta/workflows.py +66 -30
  23. wandb/bin/gpu_stats +0 -0
  24. wandb/bin/wandb-core +0 -0
  25. wandb/cli/cli.py +80 -1
  26. wandb/env.py +8 -0
  27. wandb/errors/errors.py +4 -1
  28. wandb/integration/lightning/fabric/logger.py +3 -4
  29. wandb/integration/metaflow/__init__.py +6 -0
  30. wandb/integration/metaflow/data_pandas.py +74 -0
  31. wandb/integration/metaflow/errors.py +13 -0
  32. wandb/integration/metaflow/metaflow.py +205 -190
  33. wandb/integration/openai/fine_tuning.py +1 -2
  34. wandb/jupyter.py +5 -5
  35. wandb/plot/custom_chart.py +30 -7
  36. wandb/proto/v3/wandb_internal_pb2.py +280 -280
  37. wandb/proto/v3/wandb_telemetry_pb2.py +4 -4
  38. wandb/proto/v4/wandb_internal_pb2.py +280 -280
  39. wandb/proto/v4/wandb_telemetry_pb2.py +4 -4
  40. wandb/proto/v5/wandb_internal_pb2.py +280 -280
  41. wandb/proto/v5/wandb_telemetry_pb2.py +4 -4
  42. wandb/proto/v6/wandb_internal_pb2.py +280 -280
  43. wandb/proto/v6/wandb_telemetry_pb2.py +4 -4
  44. wandb/proto/wandb_deprecated.py +6 -0
  45. wandb/sdk/artifacts/_internal_artifact.py +19 -8
  46. wandb/sdk/artifacts/_validators.py +8 -0
  47. wandb/sdk/artifacts/artifact.py +106 -75
  48. wandb/sdk/data_types/audio.py +38 -10
  49. wandb/sdk/data_types/base_types/media.py +6 -56
  50. wandb/sdk/data_types/graph.py +48 -14
  51. wandb/sdk/data_types/helper_types/bounding_boxes_2d.py +1 -3
  52. wandb/sdk/data_types/helper_types/image_mask.py +1 -3
  53. wandb/sdk/data_types/histogram.py +34 -21
  54. wandb/sdk/data_types/html.py +35 -12
  55. wandb/sdk/data_types/image.py +104 -68
  56. wandb/sdk/data_types/molecule.py +32 -19
  57. wandb/sdk/data_types/object_3d.py +36 -17
  58. wandb/sdk/data_types/plotly.py +18 -5
  59. wandb/sdk/data_types/saved_model.py +4 -6
  60. wandb/sdk/data_types/table.py +59 -30
  61. wandb/sdk/data_types/video.py +53 -26
  62. wandb/sdk/integration_utils/auto_logging.py +2 -2
  63. wandb/sdk/internal/internal_api.py +6 -0
  64. wandb/sdk/internal/job_builder.py +6 -0
  65. wandb/sdk/launch/agent/agent.py +8 -1
  66. wandb/sdk/launch/agent/run_queue_item_file_saver.py +2 -2
  67. wandb/sdk/launch/create_job.py +3 -1
  68. wandb/sdk/launch/inputs/internal.py +3 -4
  69. wandb/sdk/launch/inputs/schema.py +1 -0
  70. wandb/sdk/launch/runner/kubernetes_monitor.py +1 -0
  71. wandb/sdk/launch/runner/kubernetes_runner.py +328 -1
  72. wandb/sdk/launch/sweeps/scheduler.py +2 -3
  73. wandb/sdk/lib/asyncio_compat.py +3 -0
  74. wandb/sdk/lib/deprecate.py +1 -7
  75. wandb/sdk/lib/disabled.py +1 -1
  76. wandb/sdk/lib/hashutil.py +14 -1
  77. wandb/sdk/lib/module.py +7 -13
  78. wandb/sdk/lib/progress.py +0 -19
  79. wandb/sdk/lib/sock_client.py +0 -4
  80. wandb/sdk/wandb_init.py +66 -91
  81. wandb/sdk/wandb_login.py +18 -14
  82. wandb/sdk/wandb_metric.py +2 -0
  83. wandb/sdk/wandb_run.py +406 -414
  84. wandb/sdk/wandb_settings.py +130 -2
  85. wandb/sdk/wandb_setup.py +28 -28
  86. wandb/sdk/wandb_sweep.py +14 -13
  87. wandb/sdk/wandb_watch.py +4 -6
  88. wandb/sync/sync.py +10 -0
  89. wandb/util.py +57 -0
  90. wandb/wandb_run.py +1 -2
  91. {wandb-0.21.0.dist-info → wandb-0.21.1.dist-info}/METADATA +1 -1
  92. {wandb-0.21.0.dist-info → wandb-0.21.1.dist-info}/RECORD +95 -95
  93. wandb/vendor/pynvml/__init__.py +0 -0
  94. wandb/vendor/pynvml/pynvml.py +0 -4779
  95. {wandb-0.21.0.dist-info → wandb-0.21.1.dist-info}/WHEEL +0 -0
  96. {wandb-0.21.0.dist-info → wandb-0.21.1.dist-info}/entry_points.txt +0 -0
  97. {wandb-0.21.0.dist-info → wandb-0.21.1.dist-info}/licenses/LICENSE +0 -0
wandb/apis/public/runs.py CHANGED
@@ -1,20 +1,45 @@
1
- """Public API: runs."""
1
+ """W&B Public API for Runs.
2
+
3
+ This module provides classes for interacting with W&B runs and their associated
4
+ data.
5
+
6
+ Example:
7
+ ```python
8
+ from wandb.apis.public import Api
9
+
10
+ # Get runs matching filters
11
+ runs = Api().runs(
12
+ path="entity/project", filters={"state": "finished", "config.batch_size": 32}
13
+ )
14
+
15
+ # Access run data
16
+ for run in runs:
17
+ print(f"Run: {run.name}")
18
+ print(f"Config: {run.config}")
19
+ print(f"Metrics: {run.summary}")
20
+
21
+ # Get history with pandas
22
+ history_df = run.history(keys=["loss", "accuracy"], pandas=True)
23
+
24
+ # Work with artifacts
25
+ for artifact in run.logged_artifacts():
26
+ print(f"Artifact: {artifact.name}")
27
+ ```
28
+
29
+ Note:
30
+ This module is part of the W&B Public API and provides read/write access
31
+ to run data. For logging new runs, use the wandb.init() function from
32
+ the main wandb package.
33
+ """
34
+
35
+ from __future__ import annotations
2
36
 
3
37
  import json
4
38
  import os
5
39
  import tempfile
6
40
  import time
7
41
  import urllib
8
- from typing import (
9
- TYPE_CHECKING,
10
- Any,
11
- Collection,
12
- Dict,
13
- List,
14
- Literal,
15
- Mapping,
16
- Optional,
17
- )
42
+ from typing import TYPE_CHECKING, Any, Collection, Literal, Mapping
18
43
 
19
44
  from wandb_gql import gql
20
45
 
@@ -85,22 +110,101 @@ def _server_provides_internal_id_for_project(client) -> bool:
85
110
  ]
86
111
 
87
112
 
88
- class Runs(SizedPaginator["Run"]):
89
- """An iterable collection of runs associated with a project and optional filter.
113
+ @normalize_exceptions
114
+ def _convert_to_dict(value: Any) -> dict[str, Any]:
115
+ """Converts a value to a dictionary.
90
116
 
91
- This is generally used indirectly via the `Api`.runs method.
117
+ If the value is already a dictionary, the value is returned unchanged.
118
+ If the value is a string, bytes, or bytearray, it is parsed as JSON.
119
+ For any other type, a TypeError is raised.
120
+ """
121
+ if value is None:
122
+ return {}
123
+
124
+ if isinstance(value, dict):
125
+ return value
126
+
127
+ if isinstance(value, (str, bytes, bytearray)):
128
+ try:
129
+ return json.loads(value)
130
+ except json.decoder.JSONDecodeError:
131
+ # ignore invalid utf-8 or control characters
132
+ return json.loads(value, strict=False)
133
+
134
+ raise TypeError(f"Unable to convert {value} to a dict")
135
+
136
+
137
+ class Runs(SizedPaginator["Run"]):
138
+ """A lazy iterator of `Run` objects associated with a project and optional filter.
139
+
140
+ Runs are retrieved in pages from the W&B server as needed.
141
+
142
+ This is generally used indirectly using the `Api.runs` namespace.
143
+
144
+ Args:
145
+ client: (`wandb.apis.public.RetryingClient`) The API client to use
146
+ for requests.
147
+ entity: (str) The entity (username or team) that owns the project.
148
+ project: (str) The name of the project to fetch runs from.
149
+ filters: (Optional[Dict[str, Any]]) A dictionary of filters to apply
150
+ to the runs query.
151
+ order: (str) Order can be `created_at`, `heartbeat_at`, `config.*.value`, or `summary_metrics.*`.
152
+ If you prepend order with a + order is ascending (default).
153
+ If you prepend order with a - order is descending.
154
+ The default order is run.created_at from oldest to newest.
155
+ per_page: (int) The number of runs to fetch per request (default is 50).
156
+ include_sweeps: (bool) Whether to include sweep information in the
157
+ runs. Defaults to True.
158
+
159
+ Examples:
160
+ ```python
161
+ from wandb.apis.public.runs import Runs
162
+ from wandb.apis.public import Api
163
+
164
+ # Get all runs from a project that satisfy the filters
165
+ filters = {"state": "finished", "config.optimizer": "adam"}
166
+
167
+ runs = Api().runs(
168
+ client=api.client,
169
+ entity="entity",
170
+ project="project_name",
171
+ filters=filters,
172
+ )
173
+
174
+ # Iterate over runs and print details
175
+ for run in runs:
176
+ print(f"Run name: {run.name}")
177
+ print(f"Run ID: {run.id}")
178
+ print(f"Run URL: {run.url}")
179
+ print(f"Run state: {run.state}")
180
+ print(f"Run config: {run.config}")
181
+ print(f"Run summary: {run.summary}")
182
+ print(f"Run history (samples=5): {run.history(samples=5)}")
183
+ print("----------")
184
+
185
+ # Get histories for all runs with specific metrics
186
+ histories_df = runs.histories(
187
+ samples=100, # Number of samples per run
188
+ keys=["loss", "accuracy"], # Metrics to fetch
189
+ x_axis="_step", # X-axis metric
190
+ format="pandas", # Return as pandas DataFrame
191
+ )
192
+ ```
92
193
  """
93
194
 
94
195
  def __init__(
95
196
  self,
96
- client: "RetryingClient",
197
+ client: RetryingClient,
97
198
  entity: str,
98
199
  project: str,
99
- filters: Optional[Dict[str, Any]] = None,
100
- order: Optional[str] = None,
200
+ filters: dict[str, Any] | None = None,
201
+ order: str = "+created_at",
101
202
  per_page: int = 50,
102
203
  include_sweeps: bool = True,
103
204
  ):
205
+ if not order:
206
+ order = "+created_at"
207
+
104
208
  self.QUERY = gql(
105
209
  f"""#graphql
106
210
  query Runs($project: String!, $entity: String!, $cursor: String, $perPage: Int = 50, $order: String, $filters: JSONString) {{
@@ -144,25 +248,43 @@ class Runs(SizedPaginator["Run"]):
144
248
 
145
249
  @property
146
250
  def _length(self):
251
+ """Returns the total number of runs.
252
+
253
+ <!-- lazydoc-ignore: internal -->
254
+ """
147
255
  if not self.last_response:
148
256
  self._load_page()
149
257
  return self.last_response["project"]["runCount"]
150
258
 
151
259
  @property
152
- def more(self):
260
+ def more(self) -> bool:
261
+ """Returns whether there are more runs to fetch.
262
+
263
+ <!-- lazydoc-ignore: internal -->
264
+ """
153
265
  if self.last_response:
154
- return self.last_response["project"]["runs"]["pageInfo"]["hasNextPage"]
266
+ return bool(
267
+ self.last_response["project"]["runs"]["pageInfo"]["hasNextPage"]
268
+ )
155
269
  else:
156
270
  return True
157
271
 
158
272
  @property
159
273
  def cursor(self):
274
+ """Returns the cursor position for pagination of runs results.
275
+
276
+ <!-- lazydoc-ignore: internal -->
277
+ """
160
278
  if self.last_response:
161
279
  return self.last_response["project"]["runs"]["edges"][-1]["cursor"]
162
280
  else:
163
281
  return None
164
282
 
165
283
  def convert_objects(self):
284
+ """Converts GraphQL edges to Runs objects.
285
+
286
+ <!-- lazydoc-ignore: internal -->
287
+ """
166
288
  objs = []
167
289
  if self.last_response is None or self.last_response.get("project") is None:
168
290
  raise ValueError("Could not find project {}".format(self.project))
@@ -200,7 +322,7 @@ class Runs(SizedPaginator["Run"]):
200
322
  def histories(
201
323
  self,
202
324
  samples: int = 500,
203
- keys: Optional[List[str]] = None,
325
+ keys: list[str] | None = None,
204
326
  x_axis: str = "_step",
205
327
  format: Literal["default", "pandas", "polars"] = "default",
206
328
  stream: Literal["default", "system"] = "default",
@@ -208,15 +330,19 @@ class Runs(SizedPaginator["Run"]):
208
330
  """Return sampled history metrics for all runs that fit the filters conditions.
209
331
 
210
332
  Args:
211
- samples : (int, optional) The number of samples to return per run
212
- keys : (list[str], optional) Only return metrics for specific keys
213
- x_axis : (str, optional) Use this metric as the xAxis defaults to _step
214
- format : (Literal, optional) Format to return data in, options are "default", "pandas", "polars"
215
- stream : (Literal, optional) "default" for metrics, "system" for machine metrics
333
+ samples: The number of samples to return per run
334
+ keys: Only return metrics for specific keys
335
+ x_axis: Use this metric as the xAxis defaults to _step
336
+ format: Format to return data in, options are "default", "pandas",
337
+ "polars"
338
+ stream: "default" for metrics, "system" for machine metrics
216
339
  Returns:
217
- pandas.DataFrame: If format="pandas", returns a `pandas.DataFrame` of history metrics.
218
- polars.DataFrame: If format="polars", returns a `polars.DataFrame` of history metrics.
219
- list of dicts: If format="default", returns a list of dicts containing history metrics with a run_id key.
340
+ pandas.DataFrame: If `format="pandas"`, returns a `pandas.DataFrame`
341
+ of history metrics.
342
+ polars.DataFrame: If `format="polars"`, returns a `polars.DataFrame`
343
+ of history metrics.
344
+ list of dicts: If `format="default"`, returns a list of dicts
345
+ containing history metrics with a `run_id` key.
220
346
  """
221
347
  if format not in ("default", "pandas", "polars"):
222
348
  raise ValueError(
@@ -300,6 +426,14 @@ class Runs(SizedPaginator["Run"]):
300
426
  class Run(Attrs):
301
427
  """A single run associated with an entity and project.
302
428
 
429
+ Args:
430
+ client: The W&B API client.
431
+ entity: The entity associated with the run.
432
+ project: The project associated with the run.
433
+ run_id: The unique identifier for the run.
434
+ attrs: The attributes of the run.
435
+ include_sweeps: Whether to include sweeps in the run.
436
+
303
437
  Attributes:
304
438
  tags ([str]): a list of tags associated with the run
305
439
  url (str): the url of this run
@@ -325,11 +459,11 @@ class Run(Attrs):
325
459
 
326
460
  def __init__(
327
461
  self,
328
- client: "RetryingClient",
462
+ client: RetryingClient,
329
463
  entity: str,
330
464
  project: str,
331
465
  run_id: str,
332
- attrs: Optional[Mapping] = None,
466
+ attrs: Mapping | None = None,
333
467
  include_sweeps: bool = True,
334
468
  ):
335
469
  """Initialize a Run object.
@@ -353,27 +487,32 @@ class Run(Attrs):
353
487
  except OSError:
354
488
  pass
355
489
  self._summary = None
356
- self._metadata: Optional[Dict[str, Any]] = None
490
+ self._metadata: dict[str, Any] | None = None
357
491
  self._state = _attrs.get("state", "not found")
358
- self.server_provides_internal_id_field: Optional[bool] = None
492
+ self.server_provides_internal_id_field: bool | None = None
493
+ self._is_loaded: bool = False
359
494
 
360
495
  self.load(force=not _attrs)
361
496
 
362
497
  @property
363
498
  def state(self):
499
+ """The state of the run. Can be one of: Finished, Failed, Crashed, or Running."""
364
500
  return self._state
365
501
 
366
502
  @property
367
503
  def entity(self):
504
+ """The entity associated with the run."""
368
505
  return self._entity
369
506
 
370
507
  @property
371
508
  def username(self):
509
+ """This API is deprecated. Use `entity` instead."""
372
510
  wandb.termwarn("Run.username is deprecated. Please use Run.entity instead.")
373
511
  return self._entity
374
512
 
375
513
  @property
376
514
  def storage_id(self):
515
+ """The unique storage identifier for the run."""
377
516
  # For compatibility with wandb.Run, which has storage IDs
378
517
  # in self.storage_id and names in self.id.
379
518
 
@@ -381,33 +520,38 @@ class Run(Attrs):
381
520
 
382
521
  @property
383
522
  def id(self):
523
+ """The unique identifier for the run."""
384
524
  return self._attrs.get("name")
385
525
 
386
526
  @id.setter
387
527
  def id(self, new_id):
528
+ """Set the unique identifier for the run."""
388
529
  attrs = self._attrs
389
530
  attrs["name"] = new_id
390
531
  return new_id
391
532
 
392
533
  @property
393
534
  def name(self):
535
+ """The name of the run."""
394
536
  return self._attrs.get("displayName")
395
537
 
396
538
  @name.setter
397
539
  def name(self, new_name):
540
+ """Set the name of the run."""
398
541
  self._attrs["displayName"] = new_name
399
542
  return new_name
400
543
 
401
544
  @classmethod
402
545
  def create(
403
546
  cls,
404
- api,
405
- run_id=None,
406
- project=None,
407
- entity=None,
547
+ api: public.Api,
548
+ run_id: str | None = None,
549
+ project: str | None = None,
550
+ entity: str | None = None,
408
551
  state: Literal["running", "pending"] = "running",
409
552
  ):
410
553
  """Create a run for the given project."""
554
+ api._sentry.message("Invoking Run.create", level="info")
411
555
  run_id = run_id or runid.generate_id()
412
556
  project = project or api.settings.get("project") or "uncategorized"
413
557
  mutation = gql(
@@ -454,6 +598,7 @@ class Run(Attrs):
454
598
 
455
599
  def load(self, force=False):
456
600
  if force or not self._attrs:
601
+ self._is_loaded = False
457
602
  query = gql(f"""#graphql
458
603
  query Run($project: String!, $entity: String!, $name: String!) {{
459
604
  project(name: $project, entityName: $entity) {{
@@ -474,7 +619,6 @@ class Run(Attrs):
474
619
  ):
475
620
  raise ValueError("Could not find run {}".format(self))
476
621
  self._attrs = response["project"]["run"]
477
- self._state = self._attrs["state"]
478
622
 
479
623
  if self._include_sweeps and self.sweep_name and not self.sweep:
480
624
  # There may be a lot of runs. Don't bother pulling them all
@@ -487,32 +631,31 @@ class Run(Attrs):
487
631
  withRuns=False,
488
632
  )
489
633
 
634
+ if not self._is_loaded:
635
+ self._load_from_attrs()
636
+ self._is_loaded = True
637
+
638
+ return self._attrs
639
+
640
+ def _load_from_attrs(self):
641
+ self._state = self._attrs.get("state", None)
642
+ self._attrs["config"] = _convert_to_dict(self._attrs.get("config"))
643
+ self._attrs["summaryMetrics"] = _convert_to_dict(
644
+ self._attrs.get("summaryMetrics")
645
+ )
646
+ self._attrs["systemMetrics"] = _convert_to_dict(
647
+ self._attrs.get("systemMetrics")
648
+ )
649
+
490
650
  if "projectId" in self._attrs:
491
651
  self._project_internal_id = int(self._attrs["projectId"])
492
652
  else:
493
653
  self._project_internal_id = None
494
654
 
495
- try:
496
- self._attrs["summaryMetrics"] = (
497
- json.loads(self._attrs["summaryMetrics"])
498
- if self._attrs.get("summaryMetrics")
499
- else {}
500
- )
501
- except json.decoder.JSONDecodeError:
502
- # ignore invalid utf-8 or control characters
503
- self._attrs["summaryMetrics"] = json.loads(
504
- self._attrs["summaryMetrics"],
505
- strict=False,
506
- )
507
- self._attrs["systemMetrics"] = (
508
- json.loads(self._attrs["systemMetrics"])
509
- if self._attrs.get("systemMetrics")
510
- else {}
511
- )
512
655
  if self._attrs.get("user"):
513
656
  self.user = public.User(self.client, self._attrs["user"])
514
657
  config_user, config_raw = {}, {}
515
- for key, value in json.loads(self._attrs.get("config") or "{}").items():
658
+ for key, value in self._attrs.get("config").items():
516
659
  config = config_raw if key in WANDB_INTERNAL_KEYS else config_user
517
660
  if isinstance(value, dict) and "value" in value:
518
661
  config[key] = value["value"]
@@ -521,10 +664,10 @@ class Run(Attrs):
521
664
  config_raw.update(config_user)
522
665
  self._attrs["config"] = config_user
523
666
  self._attrs["rawconfig"] = config_raw
524
- return self._attrs
525
667
 
526
668
  @normalize_exceptions
527
669
  def wait_until_finished(self):
670
+ """Check the state of the run until it is finished."""
528
671
  query = gql(
529
672
  """
530
673
  query RunState($project: String!, $entity: String!, $name: String!) {
@@ -575,7 +718,12 @@ class Run(Attrs):
575
718
 
576
719
  @normalize_exceptions
577
720
  def delete(self, delete_artifacts=False):
578
- """Delete the given run from the wandb backend."""
721
+ """Delete the given run from the wandb backend.
722
+
723
+ Args:
724
+ delete_artifacts (bool, optional): Whether to delete the artifacts
725
+ associated with the run.
726
+ """
579
727
  mutation = gql(
580
728
  """
581
729
  mutation DeleteRun(
@@ -604,10 +752,15 @@ class Run(Attrs):
604
752
  )
605
753
 
606
754
  def save(self):
755
+ """Persist changes to the run object to the W&B backend."""
607
756
  self.update()
608
757
 
609
758
  @property
610
759
  def json_config(self):
760
+ """Return the run config as a JSON string.
761
+
762
+ <!-- lazydoc-ignore: internal -->
763
+ """
611
764
  config = {}
612
765
  if "_wandb" in self.rawconfig:
613
766
  config["_wandb"] = {"value": self.rawconfig["_wandb"], "desc": None}
@@ -653,17 +806,35 @@ class Run(Attrs):
653
806
  return [json.loads(line) for line in response["project"]["run"][node]]
654
807
 
655
808
  @normalize_exceptions
656
- def files(self, names=None, per_page=50):
657
- """Return a file path for each file named.
809
+ def files(
810
+ self,
811
+ names: list[str] | None = None,
812
+ pattern: str | None = None,
813
+ per_page: int = 50,
814
+ ):
815
+ """Returns a `Files` object for all files in the run which match the given criteria.
816
+
817
+ You can specify a list of exact file names to match, or a pattern to match against.
818
+ If both are provided, the pattern will be ignored.
658
819
 
659
820
  Args:
660
821
  names (list): names of the requested files, if empty returns all files
822
+ pattern (str, optional): Pattern to match when returning files from W&B.
823
+ This pattern uses mySQL's LIKE syntax,
824
+ so matching all files that end with .json would be "%.json".
825
+ If both names and pattern are provided, a ValueError will be raised.
661
826
  per_page (int): number of results per page.
662
827
 
663
828
  Returns:
664
829
  A `Files` object, which is an iterator over `File` objects.
665
830
  """
666
- return public.Files(self.client, self, names or [], per_page)
831
+ return public.Files(
832
+ self.client,
833
+ self,
834
+ names or [],
835
+ pattern=pattern,
836
+ per_page=per_page,
837
+ )
667
838
 
668
839
  @normalize_exceptions
669
840
  def file(self, name):
@@ -679,16 +850,17 @@ class Run(Attrs):
679
850
 
680
851
  @normalize_exceptions
681
852
  def upload_file(self, path, root="."):
682
- """Upload a file.
853
+ """Upload a local file to W&B, associating it with this run.
683
854
 
684
855
  Args:
685
- path (str): name of file to upload.
686
- root (str): the root path to save the file relative to. i.e.
687
- If you want to have the file saved in the run as "my_dir/file.txt"
856
+ path (str): Path to the file to upload. Can be absolute or relative.
857
+ root (str): The root path to save the file relative to. For example,
858
+ if you want to have the file saved in the run as "my_dir/file.txt"
688
859
  and you're currently in "my_dir" you would set root to "../".
860
+ Defaults to current directory (".").
689
861
 
690
862
  Returns:
691
- A `File` matching the name argument.
863
+ A `File` object representing the uploaded file.
692
864
  """
693
865
  api = InternalApi(
694
866
  default_settings={"entity": self.entity, "project": self.project},
@@ -697,8 +869,9 @@ class Run(Attrs):
697
869
  api.set_current_run_id(self.id)
698
870
  root = os.path.abspath(root)
699
871
  name = os.path.relpath(path, root)
872
+ upload_path = util.make_file_path_upload_safe(name)
700
873
  with open(os.path.join(root, name), "rb") as f:
701
- api.push({LogicalPath(name): f})
874
+ api.push({LogicalPath(upload_path): f})
702
875
  return public.Files(self.client, self, [name])[0]
703
876
 
704
877
  @normalize_exceptions
@@ -747,15 +920,6 @@ class Run(Attrs):
747
920
  def scan_history(self, keys=None, page_size=1000, min_step=None, max_step=None):
748
921
  """Returns an iterable collection of all history records for a run.
749
922
 
750
- Example:
751
- Export all the loss values for an example run
752
-
753
- ```python
754
- run = api.run("l2k2/examples-numpy-boston/i0wt6xua")
755
- history = run.scan_history(keys=["Loss"])
756
- losses = [row["Loss"] for row in history]
757
- ```
758
-
759
923
  Args:
760
924
  keys ([str], optional): only fetch these keys, and only fetch rows that have all of keys defined.
761
925
  page_size (int, optional): size of pages to fetch from the api.
@@ -764,6 +928,15 @@ class Run(Attrs):
764
928
 
765
929
  Returns:
766
930
  An iterable collection over history records (dict).
931
+
932
+ Example:
933
+ Export all the loss values for an example run
934
+
935
+ ```python
936
+ run = api.run("entity/project-name/run-id")
937
+ history = run.scan_history(keys=["Loss"])
938
+ losses = [row["Loss"] for row in history]
939
+ ```
767
940
  """
768
941
  if keys is not None and not isinstance(keys, list):
769
942
  wandb.termerror("keys must be specified in a list")
@@ -813,23 +986,27 @@ class Run(Attrs):
813
986
  An iterable collection of all Artifact objects logged as outputs during this run.
814
987
 
815
988
  Example:
816
- >>> import wandb
817
- >>> import tempfile
818
- >>> with tempfile.NamedTemporaryFile(
819
- ... mode="w", delete=False, suffix=".txt"
820
- ... ) as tmp:
821
- ... tmp.write("This is a test artifact")
822
- ... tmp_path = tmp.name
823
- >>> run = wandb.init(project="artifact-example")
824
- >>> artifact = wandb.Artifact("test_artifact", type="dataset")
825
- >>> artifact.add_file(tmp_path)
826
- >>> run.log_artifact(artifact)
827
- >>> run.finish()
828
- >>> api = wandb.Api()
829
- >>> finished_run = api.run(f"{run.entity}/{run.project}/{run.id}")
830
- >>> for logged_artifact in finished_run.logged_artifacts():
831
- ... print(logged_artifact.name)
832
- test_artifact
989
+ ```python
990
+ import wandb
991
+ import tempfile
992
+
993
+ with tempfile.NamedTemporaryFile(mode="w", delete=False, suffix=".txt") as tmp:
994
+ tmp.write("This is a test artifact")
995
+ tmp_path = tmp.name
996
+ run = wandb.init(project="artifact-example")
997
+ artifact = wandb.Artifact("test_artifact", type="dataset")
998
+ artifact.add_file(tmp_path)
999
+ run.log_artifact(artifact)
1000
+ run.finish()
1001
+
1002
+ api = wandb.Api()
1003
+
1004
+ finished_run = api.run(f"{run.entity}/{run.project}/{run.id}")
1005
+
1006
+ for logged_artifact in finished_run.logged_artifacts():
1007
+ print(logged_artifact.name)
1008
+ ```
1009
+
833
1010
  """
834
1011
  return public.RunArtifacts(self.client, self, mode="logged", per_page=per_page)
835
1012
 
@@ -848,15 +1025,19 @@ class Run(Attrs):
848
1025
  An iterable collection of Artifact objects explicitly used as inputs in this run.
849
1026
 
850
1027
  Example:
851
- >>> import wandb
852
- >>> run = wandb.init(project="artifact-example")
853
- >>> run.use_artifact("test_artifact:latest")
854
- >>> run.finish()
855
- >>> api = wandb.Api()
856
- >>> finished_run = api.run(f"{run.entity}/{run.project}/{run.id}")
857
- >>> for used_artifact in finished_run.used_artifacts():
858
- ... print(used_artifact.name)
859
- test_artifact
1028
+ ```python
1029
+ import wandb
1030
+
1031
+ run = wandb.init(project="artifact-example")
1032
+ run.use_artifact("test_artifact:latest")
1033
+ run.finish()
1034
+
1035
+ api = wandb.Api()
1036
+ finished_run = api.run(f"{run.entity}/{run.project}/{run.id}")
1037
+ for used_artifact in finished_run.used_artifacts():
1038
+ print(used_artifact.name)
1039
+ test_artifact
1040
+ ```
860
1041
  """
861
1042
  return public.RunArtifacts(self.client, self, mode="used", per_page=per_page)
862
1043
 
@@ -874,7 +1055,7 @@ class Run(Attrs):
874
1055
  feature's artifact swapping functionality.
875
1056
 
876
1057
  Returns:
877
- A `Artifact` object.
1058
+ An `Artifact` object.
878
1059
  """
879
1060
  api = InternalApi(
880
1061
  default_settings={"entity": self.entity, "project": self.project},
@@ -901,9 +1082,9 @@ class Run(Attrs):
901
1082
  @normalize_exceptions
902
1083
  def log_artifact(
903
1084
  self,
904
- artifact: "wandb.Artifact",
905
- aliases: Optional[Collection[str]] = None,
906
- tags: Optional[Collection[str]] = None,
1085
+ artifact: wandb.Artifact,
1086
+ aliases: Collection[str] | None = None,
1087
+ tags: Collection[str] | None = None,
907
1088
  ):
908
1089
  """Declare an artifact as output of a run.
909
1090
 
@@ -947,6 +1128,7 @@ class Run(Attrs):
947
1128
 
948
1129
  @property
949
1130
  def summary(self):
1131
+ """A mutable dict-like property that holds summary values associated with the run."""
950
1132
  if self._summary is None:
951
1133
  from wandb.old.summary import HTTPSummary
952
1134
 
@@ -956,6 +1138,7 @@ class Run(Attrs):
956
1138
 
957
1139
  @property
958
1140
  def path(self):
1141
+ """The path of the run. The path is a list containing the entity, project, and run_id."""
959
1142
  return [
960
1143
  urllib.parse.quote_plus(str(self.entity)),
961
1144
  urllib.parse.quote_plus(str(self.project)),
@@ -964,12 +1147,22 @@ class Run(Attrs):
964
1147
 
965
1148
  @property
966
1149
  def url(self):
1150
+ """The URL of the run.
1151
+
1152
+ The run URL is generated from the entity, project, and run_id. For
1153
+ SaaS users, it takes the form of `https://wandb.ai/entity/project/run_id`.
1154
+ """
967
1155
  path = self.path
968
1156
  path.insert(2, "runs")
969
1157
  return self.client.app_url + "/".join(path)
970
1158
 
971
1159
  @property
972
1160
  def metadata(self):
1161
+ """Metadata about the run from wandb-metadata.json.
1162
+
1163
+ Metadata includes the run's description, tags, start time, memory
1164
+ usage and more.
1165
+ """
973
1166
  if self._metadata is None:
974
1167
  try:
975
1168
  f = self.file("wandb-metadata.json")
@@ -985,6 +1178,7 @@ class Run(Attrs):
985
1178
 
986
1179
  @property
987
1180
  def lastHistoryStep(self): # noqa: N802
1181
+ """Returns the last step logged in the run's history."""
988
1182
  query = gql(
989
1183
  """
990
1184
  query RunHistoryKeys($project: String!, $entity: String!, $name: String!) {