wandb 0.18.2__py3-none-win32.whl → 0.18.4__py3-none-win32.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 (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.exe +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/apis/public/runs.py CHANGED
@@ -753,11 +753,62 @@ class Run(Attrs):
753
753
  )
754
754
 
755
755
  @normalize_exceptions
756
- def logged_artifacts(self, per_page=100):
756
+ def logged_artifacts(self, per_page: int = 100) -> public.RunArtifacts:
757
+ """Fetches all artifacts logged by this run.
758
+
759
+ Retrieves all output artifacts that were logged during the run. Returns a
760
+ paginated result that can be iterated over or collected into a single list.
761
+
762
+ Args:
763
+ per_page: Number of artifacts to fetch per API request.
764
+
765
+ Returns:
766
+ An iterable collection of all Artifact objects logged as outputs during this run.
767
+
768
+ Example:
769
+ >>> import wandb
770
+ >>> import tempfile
771
+ >>> with tempfile.NamedTemporaryFile(mode="w", delete=False, suffix=".txt") as tmp:
772
+ ... tmp.write("This is a test artifact")
773
+ ... tmp_path = tmp.name
774
+ >>> run = wandb.init(project="artifact-example")
775
+ >>> artifact = wandb.Artifact("test_artifact", type="dataset")
776
+ >>> artifact.add_file(tmp_path)
777
+ >>> run.log_artifact(artifact)
778
+ >>> run.finish()
779
+ >>> api = wandb.Api()
780
+ >>> finished_run = api.run(f"{run.entity}/{run.project}/{run.id}")
781
+ >>> for logged_artifact in finished_run.logged_artifacts():
782
+ ... print(logged_artifact.name)
783
+ test_artifact
784
+ """
757
785
  return public.RunArtifacts(self.client, self, mode="logged", per_page=per_page)
758
786
 
759
787
  @normalize_exceptions
760
- def used_artifacts(self, per_page=100):
788
+ def used_artifacts(self, per_page: int = 100) -> public.RunArtifacts:
789
+ """Fetches artifacts explicitly used by this run.
790
+
791
+ Retrieves only the input artifacts that were explicitly declared as used
792
+ during the run, typically via `run.use_artifact()`. Returns a paginated
793
+ result that can be iterated over or collected into a single list.
794
+
795
+ Args:
796
+ per_page: Number of artifacts to fetch per API request.
797
+
798
+ Returns:
799
+ An iterable collection of Artifact objects explicitly used as inputs in this run.
800
+
801
+ Example:
802
+ >>> import wandb
803
+ >>> run = wandb.init(project="artifact-example")
804
+ >>> run.use_artifact("test_artifact:latest")
805
+ >>> run.finish()
806
+ >>> api = wandb.Api()
807
+ >>> finished_run = api.run(f"{run.entity}/{run.project}/{run.id}")
808
+ >>> for used_artifact in finished_run.used_artifacts():
809
+ ... print(used_artifact.name)
810
+ test_artifact
811
+ """
761
812
  return public.RunArtifacts(self.client, self, mode="used", per_page=per_page)
762
813
 
763
814
  @normalize_exceptions
Binary file
wandb/bin/wandb-core CHANGED
Binary file
wandb/cli/beta.py ADDED
@@ -0,0 +1,178 @@
1
+ """Beta versions of wandb CLI commands.
2
+
3
+ These commands are experimental and may change or be removed in future versions.
4
+ """
5
+
6
+ from __future__ import annotations
7
+
8
+ import pathlib
9
+ import sys
10
+
11
+ import click
12
+
13
+ import wandb
14
+ from wandb.errors import UsageError, WandbCoreNotAvailableError
15
+ from wandb.util import get_core_path
16
+
17
+
18
+ @click.group()
19
+ def beta():
20
+ """Beta versions of wandb CLI commands. Requires wandb-core."""
21
+ # this is the future that requires wandb-core!
22
+ import wandb.env
23
+
24
+ wandb._sentry.configure_scope(process_context="wandb_beta")
25
+
26
+ if wandb.env.is_require_legacy_service():
27
+ raise UsageError(
28
+ "wandb beta commands can only be used with wandb-core. "
29
+ f"Please make sure that `{wandb.env._REQUIRE_LEGACY_SERVICE}` is not set."
30
+ )
31
+
32
+ try:
33
+ get_core_path()
34
+ except WandbCoreNotAvailableError as e:
35
+ wandb._sentry.exception(f"using `wandb beta`. failed with {e}")
36
+ click.secho(
37
+ (e),
38
+ fg="red",
39
+ err=True,
40
+ )
41
+
42
+
43
+ @beta.command(
44
+ name="sync",
45
+ context_settings={"default_map": {}},
46
+ help="Upload a training run to W&B",
47
+ )
48
+ @click.pass_context
49
+ @click.argument("wandb_dir", nargs=1, type=click.Path(exists=True))
50
+ @click.option("--id", "run_id", help="The run you want to upload to.")
51
+ @click.option("--project", "-p", help="The project you want to upload to.")
52
+ @click.option("--entity", "-e", help="The entity to scope to.")
53
+ @click.option("--skip-console", is_flag=True, default=False, help="Skip console logs")
54
+ @click.option("--append", is_flag=True, default=False, help="Append run")
55
+ @click.option(
56
+ "--include",
57
+ "-i",
58
+ help="Glob to include. Can be used multiple times.",
59
+ multiple=True,
60
+ )
61
+ @click.option(
62
+ "--exclude",
63
+ "-e",
64
+ help="Glob to exclude. Can be used multiple times.",
65
+ multiple=True,
66
+ )
67
+ @click.option(
68
+ "--mark-synced/--no-mark-synced",
69
+ is_flag=True,
70
+ default=True,
71
+ help="Mark runs as synced",
72
+ )
73
+ @click.option(
74
+ "--skip-synced/--no-skip-synced",
75
+ is_flag=True,
76
+ default=True,
77
+ help="Skip synced runs",
78
+ )
79
+ @click.option(
80
+ "--dry-run", is_flag=True, help="Perform a dry run without uploading anything."
81
+ )
82
+ def sync_beta( # noqa: C901
83
+ ctx,
84
+ wandb_dir=None,
85
+ run_id: str | None = None,
86
+ project: str | None = None,
87
+ entity: str | None = None,
88
+ skip_console: bool = False,
89
+ append: bool = False,
90
+ include: str | None = None,
91
+ exclude: str | None = None,
92
+ skip_synced: bool = True,
93
+ mark_synced: bool = True,
94
+ dry_run: bool = False,
95
+ ) -> None:
96
+ import concurrent.futures
97
+ from multiprocessing import cpu_count
98
+
99
+ paths = set()
100
+
101
+ # TODO: test file discovery logic
102
+ # include and exclude globs are evaluated relative to the provided base_path
103
+ if include:
104
+ for pattern in include:
105
+ matching_dirs = list(pathlib.Path(wandb_dir).glob(pattern))
106
+ for d in matching_dirs:
107
+ if not d.is_dir():
108
+ continue
109
+ wandb_files = [p for p in d.glob("*.wandb") if p.is_file()]
110
+ if len(wandb_files) > 1:
111
+ print(f"Multiple wandb files found in directory {d}, skipping")
112
+ elif len(wandb_files) == 1:
113
+ paths.add(d)
114
+ else:
115
+ paths.update({p.parent for p in pathlib.Path(wandb_dir).glob("**/*.wandb")})
116
+
117
+ for pattern in exclude:
118
+ matching_dirs = list(pathlib.Path(wandb_dir).glob(pattern))
119
+ for d in matching_dirs:
120
+ if not d.is_dir():
121
+ continue
122
+ if d in paths:
123
+ paths.remove(d)
124
+
125
+ # remove paths that are already synced, if requested
126
+ if skip_synced:
127
+ synced_paths = set()
128
+ for path in paths:
129
+ wandb_synced_files = [p for p in path.glob("*.wandb.synced") if p.is_file()]
130
+ if len(wandb_synced_files) > 1:
131
+ print(
132
+ f"Multiple wandb.synced files found in directory {path}, skipping"
133
+ )
134
+ elif len(wandb_synced_files) == 1:
135
+ synced_paths.add(path)
136
+ paths -= synced_paths
137
+
138
+ if run_id and len(paths) > 1:
139
+ # TODO: handle this more gracefully
140
+ click.echo("id can only be set for a single run.", err=True)
141
+ sys.exit(1)
142
+
143
+ if not paths:
144
+ click.echo("No runs to sync.")
145
+ return
146
+
147
+ click.echo("Found runs:")
148
+ for path in paths:
149
+ click.echo(f" {path}")
150
+
151
+ if dry_run:
152
+ return
153
+
154
+ wandb.sdk.wandb_setup.setup()
155
+
156
+ # TODO: make it thread-safe in the Rust code
157
+ with concurrent.futures.ProcessPoolExecutor(
158
+ max_workers=min(len(paths), cpu_count())
159
+ ) as executor:
160
+ futures = []
161
+ for path in paths:
162
+ # we already know there is only one wandb file in the directory
163
+ wandb_file = [p for p in path.glob("*.wandb") if p.is_file()][0]
164
+ future = executor.submit(
165
+ wandb._sync,
166
+ wandb_file,
167
+ run_id=run_id,
168
+ project=project,
169
+ entity=entity,
170
+ skip_console=skip_console,
171
+ append=append,
172
+ mark_synced=mark_synced,
173
+ )
174
+ futures.append(future)
175
+
176
+ # Wait for tasks to complete
177
+ for _ in concurrent.futures.as_completed(futures):
178
+ pass
wandb/cli/cli.py CHANGED
@@ -1,5 +1,3 @@
1
- #!/usr/bin/env python
2
-
3
1
  import asyncio
4
2
  import configparser
5
3
  import datetime
@@ -7,7 +5,6 @@ import getpass
7
5
  import json
8
6
  import logging
9
7
  import os
10
- import pathlib
11
8
  import shlex
12
9
  import shutil
13
10
  import subprocess
@@ -28,14 +25,11 @@ from dockerpycreds.utils import find_executable
28
25
 
29
26
  import wandb
30
27
  import wandb.env
31
-
32
- # from wandb.old.core import wandb_dir
33
28
  import wandb.errors
34
29
  import wandb.sdk.verify.verify as wandb_verify
35
30
  from wandb import Config, Error, env, util, wandb_agent, wandb_sdk
36
31
  from wandb.apis import InternalApi, PublicApi
37
32
  from wandb.apis.public import RunQueue
38
- from wandb.errors import UsageError, WandbCoreNotAvailableError
39
33
  from wandb.integration.magic import magic_install
40
34
  from wandb.sdk.artifacts.artifact_file_cache import get_artifact_file_cache
41
35
  from wandb.sdk.launch import utils as launch_utils
@@ -46,7 +40,8 @@ from wandb.sdk.launch.sweeps.scheduler import Scheduler
46
40
  from wandb.sdk.lib import filesystem
47
41
  from wandb.sdk.lib.wburls import wburls
48
42
  from wandb.sync import SyncManager, get_run_from_path, get_runs
49
- from wandb.util import get_core_path
43
+
44
+ from .beta import beta
50
45
 
51
46
  # Send cli logs to wandb/debug-cli.<username>.log by default and fallback to a temp dir.
52
47
  _wandb_dir = wandb.old.core.wandb_dir(env.get_dir())
@@ -432,170 +427,6 @@ def init(ctx, project, entity, reset, mode):
432
427
  )
433
428
 
434
429
 
435
- @cli.group()
436
- def beta():
437
- """Beta versions of wandb CLI commands. Requires wandb-core."""
438
- # this is the future that requires wandb-core!
439
- import wandb.env
440
-
441
- wandb._sentry.configure_scope(process_context="wandb_beta")
442
-
443
- if wandb.env.is_require_legacy_service():
444
- raise UsageError(
445
- "wandb beta commands can only be used with wandb-core. "
446
- f"Please make sure that `{wandb.env._REQUIRE_LEGACY_SERVICE}` is not set."
447
- )
448
-
449
- try:
450
- get_core_path()
451
- except WandbCoreNotAvailableError as e:
452
- wandb._sentry.exception(f"using `wandb beta`. failed with {e}")
453
- click.secho(
454
- (e),
455
- fg="red",
456
- err=True,
457
- )
458
-
459
-
460
- @beta.command(
461
- name="sync",
462
- context_settings=CONTEXT,
463
- help="Upload a training run to W&B",
464
- )
465
- @click.pass_context
466
- @click.argument("wandb_dir", nargs=1, type=click.Path(exists=True))
467
- @click.option("--id", "run_id", help="The run you want to upload to.")
468
- @click.option("--project", "-p", help="The project you want to upload to.")
469
- @click.option("--entity", "-e", help="The entity to scope to.")
470
- @click.option("--skip-console", is_flag=True, default=False, help="Skip console logs")
471
- @click.option("--append", is_flag=True, default=False, help="Append run")
472
- @click.option(
473
- "--include",
474
- "-i",
475
- help="Glob to include. Can be used multiple times.",
476
- multiple=True,
477
- )
478
- @click.option(
479
- "--exclude",
480
- "-e",
481
- help="Glob to exclude. Can be used multiple times.",
482
- multiple=True,
483
- )
484
- @click.option(
485
- "--mark-synced/--no-mark-synced",
486
- is_flag=True,
487
- default=True,
488
- help="Mark runs as synced",
489
- )
490
- @click.option(
491
- "--skip-synced/--no-skip-synced",
492
- is_flag=True,
493
- default=True,
494
- help="Skip synced runs",
495
- )
496
- @click.option(
497
- "--dry-run", is_flag=True, help="Perform a dry run without uploading anything."
498
- )
499
- @display_error
500
- def sync_beta(
501
- ctx,
502
- wandb_dir=None,
503
- run_id: Optional[str] = None,
504
- project: Optional[str] = None,
505
- entity: Optional[str] = None,
506
- skip_console: bool = False,
507
- append: bool = False,
508
- include: Optional[str] = None,
509
- exclude: Optional[str] = None,
510
- skip_synced: bool = True,
511
- mark_synced: bool = True,
512
- dry_run: bool = False,
513
- ):
514
- import concurrent.futures
515
- from multiprocessing import cpu_count
516
-
517
- paths = set()
518
-
519
- # TODO: test file discovery logic
520
- # include and exclude globs are evaluated relative to the provided base_path
521
- if include:
522
- for pattern in include:
523
- matching_dirs = list(pathlib.Path(wandb_dir).glob(pattern))
524
- for d in matching_dirs:
525
- if not d.is_dir():
526
- continue
527
- wandb_files = [p for p in d.glob("*.wandb") if p.is_file()]
528
- if len(wandb_files) > 1:
529
- print(f"Multiple wandb files found in directory {d}, skipping")
530
- elif len(wandb_files) == 1:
531
- paths.add(d)
532
- else:
533
- paths.update({p.parent for p in pathlib.Path(wandb_dir).glob("**/*.wandb")})
534
-
535
- for pattern in exclude:
536
- matching_dirs = list(pathlib.Path(wandb_dir).glob(pattern))
537
- for d in matching_dirs:
538
- if not d.is_dir():
539
- continue
540
- if d in paths:
541
- paths.remove(d)
542
-
543
- # remove paths that are already synced, if requested
544
- if skip_synced:
545
- synced_paths = set()
546
- for path in paths:
547
- wandb_synced_files = [p for p in path.glob("*.wandb.synced") if p.is_file()]
548
- if len(wandb_synced_files) > 1:
549
- print(
550
- f"Multiple wandb.synced files found in directory {path}, skipping"
551
- )
552
- elif len(wandb_synced_files) == 1:
553
- synced_paths.add(path)
554
- paths -= synced_paths
555
-
556
- if run_id and len(paths) > 1:
557
- # TODO: handle this more gracefully
558
- click.echo("id can only be set for a single run.", err=True)
559
- sys.exit(1)
560
-
561
- if not paths:
562
- click.echo("No runs to sync.")
563
- return
564
-
565
- click.echo("Found runs:")
566
- for path in paths:
567
- click.echo(f" {path}")
568
-
569
- if dry_run:
570
- return
571
-
572
- wandb.sdk.wandb_setup.setup()
573
-
574
- # TODO: make it thread-safe in the Rust code
575
- with concurrent.futures.ProcessPoolExecutor(
576
- max_workers=min(len(paths), cpu_count())
577
- ) as executor:
578
- futures = []
579
- for path in paths:
580
- # we already know there is only one wandb file in the directory
581
- wandb_file = [p for p in path.glob("*.wandb") if p.is_file()][0]
582
- future = executor.submit(
583
- wandb._sync,
584
- wandb_file,
585
- run_id=run_id,
586
- project=project,
587
- entity=entity,
588
- skip_console=skip_console,
589
- append=append,
590
- mark_synced=mark_synced,
591
- )
592
- futures.append(future)
593
-
594
- # Wait for tasks to complete
595
- for _ in concurrent.futures.as_completed(futures):
596
- pass
597
-
598
-
599
430
  @cli.command(
600
431
  context_settings=CONTEXT, help="Upload an offline training directory to W&B"
601
432
  )
@@ -3002,3 +2833,6 @@ def verify(host):
3002
2833
  and url_success
3003
2834
  ):
3004
2835
  sys.exit(1)
2836
+
2837
+
2838
+ cli.add_command(beta)
wandb/data_types.py CHANGED
@@ -14,6 +14,7 @@ and upload them to the W&B server.
14
14
  """
15
15
 
16
16
  from .sdk.data_types.audio import Audio
17
+ from .sdk.data_types.base_types.media import BatchableMedia, Media
17
18
  from .sdk.data_types.base_types.wb_value import WBValue
18
19
  from .sdk.data_types.bokeh import Bokeh
19
20
  from .sdk.data_types.graph import Graph, Node
@@ -56,6 +57,8 @@ __all__ = [
56
57
  "WBTraceTree",
57
58
  "_SavedModel",
58
59
  "WBValue",
60
+ "Media",
61
+ "BatchableMedia",
59
62
  # Typed Legacy Exports (I'd like to remove these)
60
63
  "ImageMask",
61
64
  "BoundingBoxes2D",