wandb 0.18.3__py3-none-win32.whl → 0.18.5__py3-none-win32.whl

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) 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 +263 -223
  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 -218
  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 -218
  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 +32 -1
  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 +126 -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 +58 -54
  37. wandb/sdk/wandb_run.py +380 -454
  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.3.dist-info → wandb-0.18.5.dist-info}/METADATA +4 -3
  42. {wandb-0.18.3.dist-info → wandb-0.18.5.dist-info}/RECORD +45 -43
  43. wandb/bin/nvidia_gpu_stats.exe +0 -0
  44. {wandb-0.18.3.dist-info → wandb-0.18.5.dist-info}/WHEEL +0 -0
  45. {wandb-0.18.3.dist-info → wandb-0.18.5.dist-info}/entry_points.txt +0 -0
  46. {wandb-0.18.3.dist-info → wandb-0.18.5.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",