wandb 0.13.10__py3-none-any.whl → 0.14.0__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- wandb/__init__.py +2 -3
- wandb/apis/__init__.py +1 -3
- wandb/apis/importers/__init__.py +4 -0
- wandb/apis/importers/base.py +312 -0
- wandb/apis/importers/mlflow.py +113 -0
- wandb/apis/internal.py +29 -2
- wandb/apis/normalize.py +6 -5
- wandb/apis/public.py +163 -180
- wandb/apis/reports/_templates.py +6 -12
- wandb/apis/reports/report.py +1 -1
- wandb/apis/reports/runset.py +1 -3
- wandb/apis/reports/util.py +12 -10
- wandb/beta/workflows.py +57 -34
- wandb/catboost/__init__.py +1 -2
- wandb/cli/cli.py +215 -133
- wandb/data_types.py +63 -56
- wandb/docker/__init__.py +78 -16
- wandb/docker/auth.py +21 -22
- wandb/env.py +0 -1
- wandb/errors/__init__.py +8 -116
- wandb/errors/term.py +1 -1
- wandb/fastai/__init__.py +1 -2
- wandb/filesync/dir_watcher.py +8 -5
- wandb/filesync/step_prepare.py +76 -75
- wandb/filesync/step_upload.py +1 -2
- wandb/integration/catboost/__init__.py +1 -3
- wandb/integration/catboost/catboost.py +8 -14
- wandb/integration/fastai/__init__.py +7 -13
- wandb/integration/gym/__init__.py +35 -4
- wandb/integration/keras/__init__.py +3 -3
- wandb/integration/keras/callbacks/metrics_logger.py +9 -8
- wandb/integration/keras/callbacks/model_checkpoint.py +9 -9
- wandb/integration/keras/callbacks/tables_builder.py +31 -19
- wandb/integration/kfp/kfp_patch.py +20 -17
- wandb/integration/kfp/wandb_logging.py +1 -2
- wandb/integration/lightgbm/__init__.py +21 -19
- wandb/integration/prodigy/prodigy.py +6 -7
- wandb/integration/sacred/__init__.py +9 -12
- wandb/integration/sagemaker/__init__.py +1 -3
- wandb/integration/sagemaker/auth.py +0 -1
- wandb/integration/sagemaker/config.py +1 -1
- wandb/integration/sagemaker/resources.py +1 -1
- wandb/integration/sb3/sb3.py +8 -4
- wandb/integration/tensorboard/__init__.py +1 -3
- wandb/integration/tensorboard/log.py +8 -8
- wandb/integration/tensorboard/monkeypatch.py +11 -9
- wandb/integration/tensorflow/__init__.py +1 -3
- wandb/integration/xgboost/__init__.py +4 -6
- wandb/integration/yolov8/__init__.py +7 -0
- wandb/integration/yolov8/yolov8.py +250 -0
- wandb/jupyter.py +31 -35
- wandb/lightgbm/__init__.py +1 -2
- wandb/old/settings.py +2 -2
- wandb/plot/bar.py +1 -2
- wandb/plot/confusion_matrix.py +1 -3
- wandb/plot/histogram.py +1 -2
- wandb/plot/line.py +1 -2
- wandb/plot/line_series.py +4 -4
- wandb/plot/pr_curve.py +17 -20
- wandb/plot/roc_curve.py +1 -3
- wandb/plot/scatter.py +1 -2
- wandb/proto/v3/wandb_server_pb2.py +85 -39
- wandb/proto/v3/wandb_telemetry_pb2.py +10 -10
- wandb/proto/v4/wandb_server_pb2.py +51 -39
- wandb/proto/v4/wandb_telemetry_pb2.py +10 -10
- wandb/sdk/__init__.py +1 -3
- wandb/sdk/backend/backend.py +1 -1
- wandb/sdk/data_types/_dtypes.py +38 -30
- wandb/sdk/data_types/base_types/json_metadata.py +1 -3
- wandb/sdk/data_types/base_types/media.py +17 -17
- wandb/sdk/data_types/base_types/wb_value.py +33 -26
- wandb/sdk/data_types/helper_types/bounding_boxes_2d.py +91 -125
- wandb/sdk/data_types/helper_types/classes.py +1 -1
- wandb/sdk/data_types/helper_types/image_mask.py +12 -12
- wandb/sdk/data_types/histogram.py +5 -4
- wandb/sdk/data_types/html.py +1 -2
- wandb/sdk/data_types/image.py +11 -11
- wandb/sdk/data_types/molecule.py +3 -6
- wandb/sdk/data_types/object_3d.py +1 -2
- wandb/sdk/data_types/plotly.py +1 -2
- wandb/sdk/data_types/saved_model.py +10 -8
- wandb/sdk/data_types/video.py +1 -1
- wandb/sdk/integration_utils/data_logging.py +5 -5
- wandb/sdk/interface/artifacts.py +288 -266
- wandb/sdk/interface/interface.py +2 -3
- wandb/sdk/interface/interface_grpc.py +1 -1
- wandb/sdk/interface/interface_queue.py +1 -1
- wandb/sdk/interface/interface_relay.py +1 -1
- wandb/sdk/interface/interface_shared.py +1 -2
- wandb/sdk/interface/interface_sock.py +1 -1
- wandb/sdk/interface/message_future.py +1 -1
- wandb/sdk/interface/message_future_poll.py +1 -1
- wandb/sdk/interface/router.py +1 -1
- wandb/sdk/interface/router_queue.py +1 -1
- wandb/sdk/interface/router_relay.py +1 -1
- wandb/sdk/interface/router_sock.py +1 -1
- wandb/sdk/interface/summary_record.py +1 -1
- wandb/sdk/internal/artifacts.py +1 -1
- wandb/sdk/internal/datastore.py +2 -3
- wandb/sdk/internal/file_pusher.py +5 -3
- wandb/sdk/internal/file_stream.py +22 -19
- wandb/sdk/internal/handler.py +5 -4
- wandb/sdk/internal/internal.py +1 -1
- wandb/sdk/internal/internal_api.py +115 -55
- wandb/sdk/internal/job_builder.py +1 -3
- wandb/sdk/internal/profiler.py +1 -1
- wandb/sdk/internal/progress.py +4 -6
- wandb/sdk/internal/sample.py +1 -3
- wandb/sdk/internal/sender.py +28 -16
- wandb/sdk/internal/settings_static.py +5 -5
- wandb/sdk/internal/system/assets/__init__.py +1 -0
- wandb/sdk/internal/system/assets/cpu.py +3 -9
- wandb/sdk/internal/system/assets/disk.py +2 -4
- wandb/sdk/internal/system/assets/gpu.py +6 -18
- wandb/sdk/internal/system/assets/gpu_apple.py +2 -4
- wandb/sdk/internal/system/assets/interfaces.py +50 -22
- wandb/sdk/internal/system/assets/ipu.py +1 -3
- wandb/sdk/internal/system/assets/memory.py +7 -13
- wandb/sdk/internal/system/assets/network.py +4 -8
- wandb/sdk/internal/system/assets/open_metrics.py +283 -0
- wandb/sdk/internal/system/assets/tpu.py +1 -4
- wandb/sdk/internal/system/assets/trainium.py +26 -14
- wandb/sdk/internal/system/system_info.py +2 -3
- wandb/sdk/internal/system/system_monitor.py +52 -20
- wandb/sdk/internal/tb_watcher.py +12 -13
- wandb/sdk/launch/_project_spec.py +54 -65
- wandb/sdk/launch/agent/agent.py +374 -90
- wandb/sdk/launch/builder/abstract.py +61 -7
- wandb/sdk/launch/builder/build.py +81 -110
- wandb/sdk/launch/builder/docker_builder.py +181 -0
- wandb/sdk/launch/builder/kaniko_builder.py +419 -0
- wandb/sdk/launch/builder/noop.py +31 -12
- wandb/sdk/launch/builder/templates/_wandb_bootstrap.py +70 -20
- wandb/sdk/launch/environment/abstract.py +28 -0
- wandb/sdk/launch/environment/aws_environment.py +276 -0
- wandb/sdk/launch/environment/gcp_environment.py +271 -0
- wandb/sdk/launch/environment/local_environment.py +65 -0
- wandb/sdk/launch/github_reference.py +3 -8
- wandb/sdk/launch/launch.py +38 -29
- wandb/sdk/launch/launch_add.py +6 -8
- wandb/sdk/launch/loader.py +230 -0
- wandb/sdk/launch/registry/abstract.py +54 -0
- wandb/sdk/launch/registry/elastic_container_registry.py +163 -0
- wandb/sdk/launch/registry/google_artifact_registry.py +203 -0
- wandb/sdk/launch/registry/local_registry.py +62 -0
- wandb/sdk/launch/runner/abstract.py +1 -16
- wandb/sdk/launch/runner/{kubernetes.py → kubernetes_runner.py} +83 -95
- wandb/sdk/launch/runner/local_container.py +46 -22
- wandb/sdk/launch/runner/local_process.py +1 -4
- wandb/sdk/launch/runner/{aws.py → sagemaker_runner.py} +53 -212
- wandb/sdk/launch/runner/{gcp_vertex.py → vertex_runner.py} +38 -55
- wandb/sdk/launch/sweeps/__init__.py +3 -2
- wandb/sdk/launch/sweeps/scheduler.py +132 -39
- wandb/sdk/launch/sweeps/scheduler_sweep.py +80 -89
- wandb/sdk/launch/utils.py +101 -30
- wandb/sdk/launch/wandb_reference.py +2 -7
- wandb/sdk/lib/_settings_toposort_generate.py +166 -0
- wandb/sdk/lib/_settings_toposort_generated.py +201 -0
- wandb/sdk/lib/apikey.py +2 -4
- wandb/sdk/lib/config_util.py +4 -1
- wandb/sdk/lib/console.py +1 -3
- wandb/sdk/lib/deprecate.py +3 -3
- wandb/sdk/lib/file_stream_utils.py +7 -5
- wandb/sdk/lib/filenames.py +1 -1
- wandb/sdk/lib/filesystem.py +61 -5
- wandb/sdk/lib/git.py +1 -3
- wandb/sdk/lib/import_hooks.py +4 -7
- wandb/sdk/lib/ipython.py +8 -5
- wandb/sdk/lib/lazyloader.py +1 -3
- wandb/sdk/lib/mailbox.py +14 -4
- wandb/sdk/lib/proto_util.py +10 -5
- wandb/sdk/lib/redirect.py +15 -22
- wandb/sdk/lib/reporting.py +1 -3
- wandb/sdk/lib/retry.py +4 -5
- wandb/sdk/lib/runid.py +1 -3
- wandb/sdk/lib/server.py +15 -9
- wandb/sdk/lib/sock_client.py +1 -1
- wandb/sdk/lib/sparkline.py +1 -1
- wandb/sdk/lib/wburls.py +1 -1
- wandb/sdk/service/port_file.py +1 -2
- wandb/sdk/service/service.py +36 -13
- wandb/sdk/service/service_base.py +12 -1
- wandb/sdk/verify/verify.py +5 -7
- wandb/sdk/wandb_artifacts.py +142 -177
- wandb/sdk/wandb_config.py +5 -8
- wandb/sdk/wandb_helper.py +1 -1
- wandb/sdk/wandb_init.py +24 -13
- wandb/sdk/wandb_login.py +9 -9
- wandb/sdk/wandb_manager.py +39 -4
- wandb/sdk/wandb_metric.py +2 -6
- wandb/sdk/wandb_require.py +4 -15
- wandb/sdk/wandb_require_helpers.py +1 -9
- wandb/sdk/wandb_run.py +95 -141
- wandb/sdk/wandb_save.py +1 -3
- wandb/sdk/wandb_settings.py +149 -54
- wandb/sdk/wandb_setup.py +66 -46
- wandb/sdk/wandb_summary.py +13 -10
- wandb/sdk/wandb_sweep.py +6 -7
- wandb/sdk/wandb_watch.py +1 -1
- wandb/sklearn/calculate/confusion_matrix.py +1 -1
- wandb/sklearn/calculate/learning_curve.py +1 -1
- wandb/sklearn/calculate/summary_metrics.py +1 -3
- wandb/sklearn/plot/__init__.py +1 -1
- wandb/sklearn/plot/classifier.py +27 -18
- wandb/sklearn/plot/clusterer.py +4 -5
- wandb/sklearn/plot/regressor.py +4 -4
- wandb/sklearn/plot/shared.py +2 -2
- wandb/sync/__init__.py +1 -3
- wandb/sync/sync.py +4 -5
- wandb/testing/relay.py +11 -10
- wandb/trigger.py +1 -1
- wandb/util.py +106 -81
- wandb/viz.py +4 -4
- wandb/wandb_agent.py +50 -50
- wandb/wandb_controller.py +2 -3
- wandb/wandb_run.py +1 -2
- wandb/wandb_torch.py +1 -1
- wandb/xgboost/__init__.py +1 -2
- {wandb-0.13.10.dist-info → wandb-0.14.0.dist-info}/METADATA +6 -2
- {wandb-0.13.10.dist-info → wandb-0.14.0.dist-info}/RECORD +224 -209
- {wandb-0.13.10.dist-info → wandb-0.14.0.dist-info}/WHEEL +1 -1
- wandb/sdk/launch/builder/docker.py +0 -80
- wandb/sdk/launch/builder/kaniko.py +0 -393
- wandb/sdk/launch/builder/loader.py +0 -32
- wandb/sdk/launch/runner/loader.py +0 -50
- {wandb-0.13.10.dist-info → wandb-0.14.0.dist-info}/LICENSE +0 -0
- {wandb-0.13.10.dist-info → wandb-0.14.0.dist-info}/entry_points.txt +0 -0
- {wandb-0.13.10.dist-info → wandb-0.14.0.dist-info}/top_level.txt +0 -0
wandb/apis/public.py
CHANGED
@@ -47,11 +47,16 @@ from wandb import __version__, env, util
|
|
47
47
|
from wandb.apis.internal import Api as InternalApi
|
48
48
|
from wandb.apis.normalize import normalize_exceptions
|
49
49
|
from wandb.data_types import WBValue
|
50
|
-
from wandb.errors import CommError
|
50
|
+
from wandb.errors import CommError
|
51
51
|
from wandb.errors.term import termlog
|
52
52
|
from wandb.sdk.data_types._dtypes import InvalidType, Type, TypeRegistry
|
53
53
|
from wandb.sdk.interface import artifacts
|
54
|
-
from wandb.sdk.launch.utils import
|
54
|
+
from wandb.sdk.launch.utils import (
|
55
|
+
LAUNCH_DEFAULT_PROJECT,
|
56
|
+
LaunchError,
|
57
|
+
_fetch_git_repo,
|
58
|
+
apply_patch,
|
59
|
+
)
|
55
60
|
from wandb.sdk.lib import filesystem, ipython, retry, runid
|
56
61
|
from wandb.sdk.lib.hashutil import b64_to_hex_id, hex_to_b64_id, md5_file_b64
|
57
62
|
|
@@ -269,8 +274,7 @@ class RetryingClient:
|
|
269
274
|
|
270
275
|
|
271
276
|
class Api:
|
272
|
-
"""
|
273
|
-
Used for querying the wandb server.
|
277
|
+
"""Used for querying the wandb server.
|
274
278
|
|
275
279
|
Examples:
|
276
280
|
Most common way to initialize
|
@@ -433,7 +437,7 @@ class Api:
|
|
433
437
|
self._client = RetryingClient(self._base_client)
|
434
438
|
|
435
439
|
def create_run(self, **kwargs):
|
436
|
-
"""Create a new run"""
|
440
|
+
"""Create a new run."""
|
437
441
|
if kwargs.get("entity") is None:
|
438
442
|
kwargs["entity"] = self.default_entity
|
439
443
|
return Run.create(self, **kwargs)
|
@@ -459,8 +463,7 @@ class Api:
|
|
459
463
|
self.client.execute(self.CREATE_PROJECT, {"entityName": entity, "name": name})
|
460
464
|
|
461
465
|
def load_report(self, path: str) -> "wandb.apis.reports.Report":
|
462
|
-
"""
|
463
|
-
Get report at a given path.
|
466
|
+
"""Get report at a given path.
|
464
467
|
|
465
468
|
Arguments:
|
466
469
|
path: (str) Path to the target report in the form `entity/project/reports/reportId`.
|
@@ -476,7 +479,7 @@ class Api:
|
|
476
479
|
return wandb.apis.reports.Report.from_url(path)
|
477
480
|
|
478
481
|
def create_user(self, email, admin=False):
|
479
|
-
"""
|
482
|
+
"""Create a new user.
|
480
483
|
|
481
484
|
Arguments:
|
482
485
|
email: (str) The name of the team
|
@@ -488,8 +491,8 @@ class Api:
|
|
488
491
|
return User.create(self, email, admin)
|
489
492
|
|
490
493
|
def sync_tensorboard(self, root_dir, run_id=None, project=None, entity=None):
|
491
|
-
"""Sync a local directory containing tfevent files to wandb"""
|
492
|
-
from wandb.sync import SyncManager #
|
494
|
+
"""Sync a local directory containing tfevent files to wandb."""
|
495
|
+
from wandb.sync import SyncManager # TODO: circular import madness
|
493
496
|
|
494
497
|
run_id = run_id or runid.generate_id()
|
495
498
|
project = project or self.settings.get("project") or "uncategorized"
|
@@ -550,15 +553,16 @@ class Api:
|
|
550
553
|
return self._viewer
|
551
554
|
|
552
555
|
def flush(self):
|
553
|
-
"""
|
556
|
+
"""Flush the local cache.
|
557
|
+
|
554
558
|
The api object keeps a local cache of runs, so if the state of the run may
|
555
|
-
change while executing your script you must clear the local cache with
|
556
|
-
to get the latest values associated with the run.
|
559
|
+
change while executing your script you must clear the local cache with
|
560
|
+
`api.flush()` to get the latest values associated with the run.
|
557
561
|
"""
|
558
562
|
self._runs = {}
|
559
563
|
|
560
564
|
def from_path(self, path):
|
561
|
-
"""Return a run, sweep, project or report from a path
|
565
|
+
"""Return a run, sweep, project or report from a path.
|
562
566
|
|
563
567
|
Examples:
|
564
568
|
```
|
@@ -614,7 +618,7 @@ class Api:
|
|
614
618
|
)
|
615
619
|
|
616
620
|
def _parse_project_path(self, path):
|
617
|
-
"""
|
621
|
+
"""Return project and entity for project specified by path."""
|
618
622
|
project = self.settings["project"]
|
619
623
|
entity = self.settings["entity"] or self.default_entity
|
620
624
|
if path is None:
|
@@ -625,13 +629,14 @@ class Api:
|
|
625
629
|
return parts
|
626
630
|
|
627
631
|
def _parse_path(self, path):
|
628
|
-
"""
|
632
|
+
"""Parse url, filepath, or docker paths.
|
629
633
|
|
630
|
-
|
631
|
-
|
632
|
-
|
634
|
+
Allows paths in the following formats:
|
635
|
+
- url: entity/project/runs/id
|
636
|
+
- path: entity/project/id
|
637
|
+
- docker: entity/project:id
|
633
638
|
|
634
|
-
|
639
|
+
Entity is optional and will fall back to the current logged-in user.
|
635
640
|
"""
|
636
641
|
project = self.settings["project"]
|
637
642
|
entity = self.settings["entity"] or self.default_entity
|
@@ -656,7 +661,7 @@ class Api:
|
|
656
661
|
return entity, project, id
|
657
662
|
|
658
663
|
def _parse_artifact_path(self, path):
|
659
|
-
"""
|
664
|
+
"""Return project, entity and artifact name for project specified by path."""
|
660
665
|
project = self.settings["project"]
|
661
666
|
entity = self.settings["entity"] or self.default_entity
|
662
667
|
if path is None:
|
@@ -671,8 +676,7 @@ class Api:
|
|
671
676
|
return parts
|
672
677
|
|
673
678
|
def projects(self, entity=None, per_page=200):
|
674
|
-
"""
|
675
|
-
Get projects for a given entity.
|
679
|
+
"""Get projects for a given entity.
|
676
680
|
|
677
681
|
Arguments:
|
678
682
|
entity: (str) Name of the entity requested. If None, will fall back to
|
@@ -731,7 +735,7 @@ class Api:
|
|
731
735
|
return self._reports[key]
|
732
736
|
|
733
737
|
def create_team(self, team, admin_username=None):
|
734
|
-
"""
|
738
|
+
"""Create a new team.
|
735
739
|
|
736
740
|
Arguments:
|
737
741
|
team: (str) The name of the team
|
@@ -746,7 +750,7 @@ class Api:
|
|
746
750
|
return Team(self.client, team)
|
747
751
|
|
748
752
|
def user(self, username_or_email):
|
749
|
-
"""Return a user from a username or email address
|
753
|
+
"""Return a user from a username or email address.
|
750
754
|
|
751
755
|
Note: This function only works for Local Admins, if you are trying to get your own user object, please use `api.viewer`.
|
752
756
|
|
@@ -768,7 +772,7 @@ class Api:
|
|
768
772
|
return User(self._client, res["users"]["edges"][0]["node"])
|
769
773
|
|
770
774
|
def users(self, username_or_email):
|
771
|
-
"""Return all users from a partial username or email address query
|
775
|
+
"""Return all users from a partial username or email address query.
|
772
776
|
|
773
777
|
Note: This function only works for Local Admins, if you are trying to get your own user object, please use `api.viewer`.
|
774
778
|
|
@@ -789,8 +793,7 @@ class Api:
|
|
789
793
|
per_page: int = 50,
|
790
794
|
include_sweeps: bool = True,
|
791
795
|
):
|
792
|
-
"""
|
793
|
-
Return a set of runs from a project that match the filters provided.
|
796
|
+
"""Return a set of runs from a project that match the filters provided.
|
794
797
|
|
795
798
|
You can filter by `config.*`, `summary_metrics.*`, `tags`, `state`, `entity`, `createdAt`, etc.
|
796
799
|
|
@@ -862,8 +865,7 @@ class Api:
|
|
862
865
|
|
863
866
|
@normalize_exceptions
|
864
867
|
def run(self, path=""):
|
865
|
-
"""
|
866
|
-
Returns a single run by parsing path in the form entity/project/run_id.
|
868
|
+
"""Return a single run by parsing path in the form entity/project/run_id.
|
867
869
|
|
868
870
|
Arguments:
|
869
871
|
path: (str) path to run in the form `entity/project/run_id`.
|
@@ -887,8 +889,9 @@ class Api:
|
|
887
889
|
container_job=False,
|
888
890
|
project_queue=None,
|
889
891
|
):
|
890
|
-
"""
|
891
|
-
|
892
|
+
"""Return a single queued run based on the path.
|
893
|
+
|
894
|
+
Parses paths of the form entity/project/queue_id/run_queue_item_id.
|
892
895
|
"""
|
893
896
|
return QueuedRun(
|
894
897
|
self.client,
|
@@ -902,8 +905,7 @@ class Api:
|
|
902
905
|
|
903
906
|
@normalize_exceptions
|
904
907
|
def sweep(self, path=""):
|
905
|
-
"""
|
906
|
-
Returns a sweep by parsing path in the form `entity/project/sweep_id`.
|
908
|
+
"""Return a sweep by parsing path in the form `entity/project/sweep_id`.
|
907
909
|
|
908
910
|
Arguments:
|
909
911
|
path: (str, optional) path to sweep in the form entity/project/sweep_id. If `api.entity`
|
@@ -936,8 +938,7 @@ class Api:
|
|
936
938
|
|
937
939
|
@normalize_exceptions
|
938
940
|
def artifact(self, name, type=None):
|
939
|
-
"""
|
940
|
-
Returns a single artifact by parsing path in the form `entity/project/run_id`.
|
941
|
+
"""Return a single artifact by parsing path in the form `entity/project/run_id`.
|
941
942
|
|
942
943
|
Arguments:
|
943
944
|
name: (str) An artifact name. May be prefixed with entity/project. Valid names
|
@@ -946,6 +947,7 @@ class Api:
|
|
946
947
|
name:alias
|
947
948
|
digest
|
948
949
|
type: (str, optional) The type of artifact to fetch.
|
950
|
+
|
949
951
|
Returns:
|
950
952
|
A `Artifact` object.
|
951
953
|
"""
|
@@ -975,7 +977,7 @@ class Attrs:
|
|
975
977
|
return camel[0].lower() + camel[1:]
|
976
978
|
|
977
979
|
def display(self, height=420, hidden=False) -> bool:
|
978
|
-
"""Display this object in jupyter"""
|
980
|
+
"""Display this object in jupyter."""
|
979
981
|
html = self.to_html(height, hidden)
|
980
982
|
if html is None:
|
981
983
|
wandb.termwarn("This object does not support `.display()`")
|
@@ -1125,14 +1127,14 @@ class User(Attrs):
|
|
1125
1127
|
|
1126
1128
|
@property
|
1127
1129
|
def user_api(self):
|
1128
|
-
"""An instance of the api using credentials from the user"""
|
1130
|
+
"""An instance of the api using credentials from the user."""
|
1129
1131
|
if self._user_api is None and len(self.api_keys) > 0:
|
1130
1132
|
self._user_api = wandb.Api(api_key=self.api_keys[0])
|
1131
1133
|
return self._user_api
|
1132
1134
|
|
1133
1135
|
@classmethod
|
1134
1136
|
def create(cls, api, email, admin=False):
|
1135
|
-
"""
|
1137
|
+
"""Create a new user.
|
1136
1138
|
|
1137
1139
|
Arguments:
|
1138
1140
|
api: (`Api`) The api instance to use
|
@@ -1161,7 +1163,7 @@ class User(Attrs):
|
|
1161
1163
|
return [k["node"]["name"] for k in self._attrs["teams"]["edges"]]
|
1162
1164
|
|
1163
1165
|
def delete_api_key(self, api_key):
|
1164
|
-
"""Delete a
|
1166
|
+
"""Delete a user's api key.
|
1165
1167
|
|
1166
1168
|
Returns:
|
1167
1169
|
Boolean indicating success
|
@@ -1180,7 +1182,7 @@ class User(Attrs):
|
|
1180
1182
|
return True
|
1181
1183
|
|
1182
1184
|
def generate_api_key(self, description=None):
|
1183
|
-
"""
|
1185
|
+
"""Generate a new api key.
|
1184
1186
|
|
1185
1187
|
Returns:
|
1186
1188
|
The new api key, or None on failure
|
@@ -1225,7 +1227,7 @@ class Member(Attrs):
|
|
1225
1227
|
self.team = team
|
1226
1228
|
|
1227
1229
|
def delete(self):
|
1228
|
-
"""Remove a member from a team
|
1230
|
+
"""Remove a member from a team.
|
1229
1231
|
|
1230
1232
|
Returns:
|
1231
1233
|
Boolean indicating success
|
@@ -1327,7 +1329,7 @@ class Team(Attrs):
|
|
1327
1329
|
|
1328
1330
|
@classmethod
|
1329
1331
|
def create(cls, api, team, admin_username=None):
|
1330
|
-
"""
|
1332
|
+
"""Create a new team.
|
1331
1333
|
|
1332
1334
|
Arguments:
|
1333
1335
|
api: (`Api`) The api instance to use
|
@@ -1347,7 +1349,7 @@ class Team(Attrs):
|
|
1347
1349
|
return Team(api.client, team)
|
1348
1350
|
|
1349
1351
|
def invite(self, username_or_email, admin=False):
|
1350
|
-
"""
|
1352
|
+
"""Invite a user to a team.
|
1351
1353
|
|
1352
1354
|
Arguments:
|
1353
1355
|
username_or_email: (str) The username or email address of the user you want to invite
|
@@ -1368,7 +1370,7 @@ class Team(Attrs):
|
|
1368
1370
|
return True
|
1369
1371
|
|
1370
1372
|
def create_service_account(self, description):
|
1371
|
-
"""
|
1373
|
+
"""Create a service account for the team.
|
1372
1374
|
|
1373
1375
|
Arguments:
|
1374
1376
|
description: (str) A description for this service account
|
@@ -1401,9 +1403,7 @@ class Team(Attrs):
|
|
1401
1403
|
|
1402
1404
|
|
1403
1405
|
class Projects(Paginator):
|
1404
|
-
"""
|
1405
|
-
An iterable collection of `Project` objects.
|
1406
|
-
"""
|
1406
|
+
"""An iterable collection of `Project` objects."""
|
1407
1407
|
|
1408
1408
|
QUERY = gql(
|
1409
1409
|
"""
|
@@ -1480,7 +1480,7 @@ class Project(Attrs):
|
|
1480
1480
|
return self.client.app_url + "/".join(self.path + ["workspace"])
|
1481
1481
|
|
1482
1482
|
def to_html(self, height=420, hidden=False):
|
1483
|
-
"""Generate HTML containing an iframe displaying this project"""
|
1483
|
+
"""Generate HTML containing an iframe displaying this project."""
|
1484
1484
|
url = self.url + "?jupyter=true"
|
1485
1485
|
style = f"border:none;width:100%;height:{height}px;"
|
1486
1486
|
prefix = ""
|
@@ -1549,7 +1549,8 @@ class Project(Attrs):
|
|
1549
1549
|
|
1550
1550
|
class Runs(Paginator):
|
1551
1551
|
"""An iterable collection of runs associated with a project and optional filter.
|
1552
|
-
|
1552
|
+
|
1553
|
+
This is generally used indirectly via the `Api`.runs method.
|
1553
1554
|
"""
|
1554
1555
|
|
1555
1556
|
QUERY = gql(
|
@@ -1661,8 +1662,7 @@ class Runs(Paginator):
|
|
1661
1662
|
|
1662
1663
|
|
1663
1664
|
class Run(Attrs):
|
1664
|
-
"""
|
1665
|
-
A single run associated with an entity and project.
|
1665
|
+
"""A single run associated with an entity and project.
|
1666
1666
|
|
1667
1667
|
Attributes:
|
1668
1668
|
tags ([str]): a list of tags associated with the run
|
@@ -1694,8 +1694,10 @@ class Run(Attrs):
|
|
1694
1694
|
attrs: Optional[Mapping] = None,
|
1695
1695
|
include_sweeps: bool = True,
|
1696
1696
|
):
|
1697
|
-
"""
|
1698
|
-
|
1697
|
+
"""Initialize a Run object.
|
1698
|
+
|
1699
|
+
Run is always initialized by calling api.runs() where api is an instance of
|
1700
|
+
wandb.Api.
|
1699
1701
|
"""
|
1700
1702
|
_attrs = attrs or {}
|
1701
1703
|
super().__init__(dict(_attrs))
|
@@ -1758,7 +1760,7 @@ class Run(Attrs):
|
|
1758
1760
|
|
1759
1761
|
@classmethod
|
1760
1762
|
def create(cls, api, run_id=None, project=None, entity=None):
|
1761
|
-
"""Create a run for the given project"""
|
1763
|
+
"""Create a run for the given project."""
|
1762
1764
|
run_id = run_id or runid.generate_id()
|
1763
1765
|
project = project or api.settings.get("project") or "uncategorized"
|
1764
1766
|
mutation = gql(
|
@@ -1883,9 +1885,7 @@ class Run(Attrs):
|
|
1883
1885
|
|
1884
1886
|
@normalize_exceptions
|
1885
1887
|
def update(self):
|
1886
|
-
"""
|
1887
|
-
Persists changes to the run object to the wandb backend.
|
1888
|
-
"""
|
1888
|
+
"""Persist changes to the run object to the wandb backend."""
|
1889
1889
|
mutation = gql(
|
1890
1890
|
"""
|
1891
1891
|
mutation UpsertBucket($id: String!, $description: String, $display_name: String, $notes: String, $tags: [String!], $config: JSONString!, $groupName: String) {
|
@@ -1913,9 +1913,7 @@ class Run(Attrs):
|
|
1913
1913
|
|
1914
1914
|
@normalize_exceptions
|
1915
1915
|
def delete(self, delete_artifacts=False):
|
1916
|
-
"""
|
1917
|
-
Deletes the given run from the wandb backend.
|
1918
|
-
"""
|
1916
|
+
"""Delete the given run from the wandb backend."""
|
1919
1917
|
mutation = gql(
|
1920
1918
|
"""
|
1921
1919
|
mutation DeleteRun(
|
@@ -1958,7 +1956,7 @@ class Run(Attrs):
|
|
1958
1956
|
return json.dumps(config)
|
1959
1957
|
|
1960
1958
|
def _exec(self, query, **kwargs):
|
1961
|
-
"""Execute a query against the cloud backend"""
|
1959
|
+
"""Execute a query against the cloud backend."""
|
1962
1960
|
variables = {"entity": self.entity, "project": self.project, "name": self.id}
|
1963
1961
|
variables.update(kwargs)
|
1964
1962
|
return self.client.execute(query, variable_values=variables)
|
@@ -1997,10 +1995,11 @@ class Run(Attrs):
|
|
1997
1995
|
|
1998
1996
|
@normalize_exceptions
|
1999
1997
|
def files(self, names=None, per_page=50):
|
2000
|
-
"""
|
1998
|
+
"""Return a file path for each file named.
|
1999
|
+
|
2001
2000
|
Arguments:
|
2002
2001
|
names (list): names of the requested files, if empty returns all files
|
2003
|
-
per_page (int): number of results per page
|
2002
|
+
per_page (int): number of results per page.
|
2004
2003
|
|
2005
2004
|
Returns:
|
2006
2005
|
A `Files` object, which is an iterator over `File` objects.
|
@@ -2009,7 +2008,8 @@ class Run(Attrs):
|
|
2009
2008
|
|
2010
2009
|
@normalize_exceptions
|
2011
2010
|
def file(self, name):
|
2012
|
-
"""
|
2011
|
+
"""Return the path of a file with a given name in the artifact.
|
2012
|
+
|
2013
2013
|
Arguments:
|
2014
2014
|
name (str): name of requested file.
|
2015
2015
|
|
@@ -2020,12 +2020,13 @@ class Run(Attrs):
|
|
2020
2020
|
|
2021
2021
|
@normalize_exceptions
|
2022
2022
|
def upload_file(self, path, root="."):
|
2023
|
-
"""
|
2023
|
+
"""Upload a file.
|
2024
|
+
|
2024
2025
|
Arguments:
|
2025
2026
|
path (str): name of file to upload.
|
2026
2027
|
root (str): the root path to save the file relative to. i.e.
|
2027
2028
|
If you want to have the file saved in the run as "my_dir/file.txt"
|
2028
|
-
and you're currently in "my_dir" you would set root to "../"
|
2029
|
+
and you're currently in "my_dir" you would set root to "../".
|
2029
2030
|
|
2030
2031
|
Returns:
|
2031
2032
|
A `File` matching the name argument.
|
@@ -2045,20 +2046,21 @@ class Run(Attrs):
|
|
2045
2046
|
def history(
|
2046
2047
|
self, samples=500, keys=None, x_axis="_step", pandas=True, stream="default"
|
2047
2048
|
):
|
2048
|
-
"""
|
2049
|
-
|
2050
|
-
the history records being sampled.
|
2049
|
+
"""Return sampled history metrics for a run.
|
2050
|
+
|
2051
|
+
This is simpler and faster if you are ok with the history records being sampled.
|
2051
2052
|
|
2052
2053
|
Arguments:
|
2053
|
-
samples (int, optional)
|
2054
|
-
pandas (bool, optional)
|
2055
|
-
keys (list, optional)
|
2056
|
-
x_axis (str, optional)
|
2057
|
-
stream (str, optional)
|
2054
|
+
samples : (int, optional) The number of samples to return
|
2055
|
+
pandas : (bool, optional) Return a pandas dataframe
|
2056
|
+
keys : (list, optional) Only return metrics for specific keys
|
2057
|
+
x_axis : (str, optional) Use this metric as the xAxis defaults to _step
|
2058
|
+
stream : (str, optional) "default" for metrics, "system" for machine metrics
|
2058
2059
|
|
2059
2060
|
Returns:
|
2060
|
-
If pandas=True returns a `pandas.DataFrame` of history
|
2061
|
-
|
2061
|
+
pandas.DataFrame: If pandas=True returns a `pandas.DataFrame` of history
|
2062
|
+
metrics.
|
2063
|
+
list of dicts: If pandas=False returns a list of dicts of history metrics.
|
2062
2064
|
"""
|
2063
2065
|
if keys is not None and not isinstance(keys, list):
|
2064
2066
|
wandb.termerror("keys must be specified in a list")
|
@@ -2084,8 +2086,7 @@ class Run(Attrs):
|
|
2084
2086
|
|
2085
2087
|
@normalize_exceptions
|
2086
2088
|
def scan_history(self, keys=None, page_size=1000, min_step=None, max_step=None):
|
2087
|
-
"""
|
2088
|
-
Returns an iterable collection of all history records for a run.
|
2089
|
+
"""Returns an iterable collection of all history records for a run.
|
2089
2090
|
|
2090
2091
|
Example:
|
2091
2092
|
Export all the loss values for an example run
|
@@ -2158,6 +2159,7 @@ class Run(Attrs):
|
|
2158
2159
|
to easily differentiate artifacts used in a
|
2159
2160
|
run, when using the beta wandb launch
|
2160
2161
|
feature's artifact swapping functionality.
|
2162
|
+
|
2161
2163
|
Returns:
|
2162
2164
|
A `Artifact` object.
|
2163
2165
|
"""
|
@@ -2258,7 +2260,7 @@ class Run(Attrs):
|
|
2258
2260
|
return history_keys["lastStep"] if "lastStep" in history_keys else -1
|
2259
2261
|
|
2260
2262
|
def to_html(self, height=420, hidden=False):
|
2261
|
-
"""Generate HTML containing an iframe displaying this run"""
|
2263
|
+
"""Generate HTML containing an iframe displaying this run."""
|
2262
2264
|
url = self.url + "?jupyter=true"
|
2263
2265
|
style = f"border:none;width:100%;height:{height}px;"
|
2264
2266
|
prefix = ""
|
@@ -2275,9 +2277,7 @@ class Run(Attrs):
|
|
2275
2277
|
|
2276
2278
|
|
2277
2279
|
class QueuedRun:
|
2278
|
-
"""
|
2279
|
-
A single queued run associated with an entity and project. Call `run = wait_until_running()` or `run = wait_until_finished()` methods to access the run
|
2280
|
-
"""
|
2280
|
+
"""A single queued run associated with an entity and project. Call `run = wait_until_running()` or `run = wait_until_finished()` methods to access the run."""
|
2281
2281
|
|
2282
2282
|
def __init__(
|
2283
2283
|
self,
|
@@ -2402,9 +2402,7 @@ class QueuedRun:
|
|
2402
2402
|
|
2403
2403
|
@normalize_exceptions
|
2404
2404
|
def delete(self, delete_artifacts=False):
|
2405
|
-
"""
|
2406
|
-
Deletes the given queued run from the wandb backend.
|
2407
|
-
"""
|
2405
|
+
"""Delete the given queued run from the wandb backend."""
|
2408
2406
|
query = gql(
|
2409
2407
|
"""
|
2410
2408
|
query fetchRunQueuesFromProject($entityName: String!, $projectName: String!, $runQueueName: String!) {
|
@@ -2582,7 +2580,7 @@ class Sweep(Attrs):
|
|
2582
2580
|
)
|
2583
2581
|
|
2584
2582
|
def best_run(self, order=None):
|
2585
|
-
"
|
2583
|
+
"""Return the best run sorted by the metric defined in config or the order passed in."""
|
2586
2584
|
if order is None:
|
2587
2585
|
order = self.order
|
2588
2586
|
else:
|
@@ -2608,7 +2606,7 @@ class Sweep(Attrs):
|
|
2608
2606
|
|
2609
2607
|
@property
|
2610
2608
|
def expected_run_count(self) -> Optional[int]:
|
2611
|
-
"
|
2609
|
+
"""Return the number of expected runs in the sweep or None for infinite runs."""
|
2612
2610
|
return self._attrs.get("runCountExpected")
|
2613
2611
|
|
2614
2612
|
@property
|
@@ -2640,7 +2638,7 @@ class Sweep(Attrs):
|
|
2640
2638
|
query=None,
|
2641
2639
|
**kwargs,
|
2642
2640
|
):
|
2643
|
-
"""Execute a query against the cloud backend"""
|
2641
|
+
"""Execute a query against the cloud backend."""
|
2644
2642
|
if query is None:
|
2645
2643
|
query = cls.QUERY
|
2646
2644
|
|
@@ -2681,7 +2679,7 @@ class Sweep(Attrs):
|
|
2681
2679
|
return sweep
|
2682
2680
|
|
2683
2681
|
def to_html(self, height=420, hidden=False):
|
2684
|
-
"""Generate HTML containing an iframe displaying this sweep"""
|
2682
|
+
"""Generate HTML containing an iframe displaying this sweep."""
|
2685
2683
|
url = self.url + "?jupyter=true"
|
2686
2684
|
style = f"border:none;width:100%;height:{height}px;"
|
2687
2685
|
prefix = ""
|
@@ -2940,7 +2938,7 @@ class Reports(Paginator):
|
|
2940
2938
|
|
2941
2939
|
|
2942
2940
|
class QueryGenerator:
|
2943
|
-
"""QueryGenerator is a helper object to write filters for runs"""
|
2941
|
+
"""QueryGenerator is a helper object to write filters for runs."""
|
2944
2942
|
|
2945
2943
|
INDIVIDUAL_OP_TO_MONGO = {
|
2946
2944
|
"!=": "$ne",
|
@@ -3195,15 +3193,15 @@ class PythonMongoishQueryGenerator:
|
|
3195
3193
|
|
3196
3194
|
def _replace_numeric_dots(self, s):
|
3197
3195
|
numeric_dots = []
|
3198
|
-
for i, (
|
3199
|
-
if
|
3196
|
+
for i, (left, mid, right) in enumerate(zip(s, s[1:], s[2:]), 1):
|
3197
|
+
if mid == ".":
|
3200
3198
|
if (
|
3201
|
-
|
3202
|
-
and
|
3203
|
-
or
|
3204
|
-
and
|
3205
|
-
or
|
3206
|
-
and
|
3199
|
+
left.isdigit()
|
3200
|
+
and right.isdigit() # 1.2
|
3201
|
+
or left.isdigit()
|
3202
|
+
and right == " " # 1.
|
3203
|
+
or left == " "
|
3204
|
+
and right.isdigit() # .2
|
3207
3205
|
):
|
3208
3206
|
numeric_dots.append(i)
|
3209
3207
|
# Edge: Catch number ending in dot at end of string
|
@@ -3459,7 +3457,7 @@ class BetaReport(Attrs):
|
|
3459
3457
|
)
|
3460
3458
|
|
3461
3459
|
def to_html(self, height=1024, hidden=False):
|
3462
|
-
"""Generate HTML containing an iframe displaying this report"""
|
3460
|
+
"""Generate HTML containing an iframe displaying this report."""
|
3463
3461
|
url = self.url + "?jupyter=true"
|
3464
3462
|
style = f"border:none;width:100%;height:{height}px;"
|
3465
3463
|
prefix = ""
|
@@ -3997,7 +3995,7 @@ class ArtifactType:
|
|
3997
3995
|
|
3998
3996
|
@normalize_exceptions
|
3999
3997
|
def collections(self, per_page=50):
|
4000
|
-
"""Artifact collections"""
|
3998
|
+
"""Artifact collections."""
|
4001
3999
|
return ProjectArtifactCollections(
|
4002
4000
|
self.client, self.entity, self.project, self.type
|
4003
4001
|
)
|
@@ -4037,7 +4035,7 @@ class ArtifactCollection:
|
|
4037
4035
|
|
4038
4036
|
@normalize_exceptions
|
4039
4037
|
def versions(self, per_page=50):
|
4040
|
-
"""Artifact versions"""
|
4038
|
+
"""Artifact versions."""
|
4041
4039
|
return ArtifactVersions(
|
4042
4040
|
self.client,
|
4043
4041
|
self.entity,
|
@@ -4049,7 +4047,7 @@ class ArtifactCollection:
|
|
4049
4047
|
|
4050
4048
|
@property
|
4051
4049
|
def aliases(self):
|
4052
|
-
"""Artifact Collection Aliases"""
|
4050
|
+
"""Artifact Collection Aliases."""
|
4053
4051
|
return self._aliases
|
4054
4052
|
|
4055
4053
|
def load(self):
|
@@ -4137,37 +4135,27 @@ class _DownloadedArtifactEntry(artifacts.ArtifactManifestEntry):
|
|
4137
4135
|
return self._parent_artifact
|
4138
4136
|
|
4139
4137
|
def copy(self, cache_path, target_path):
|
4140
|
-
|
4141
|
-
if platform.system() == "Windows":
|
4142
|
-
head, tail = os.path.splitdrive(target_path)
|
4143
|
-
target_path = head + tail.replace(":", "-")
|
4144
|
-
|
4145
|
-
need_copy = (
|
4146
|
-
not os.path.isfile(target_path)
|
4147
|
-
or os.stat(cache_path).st_mtime != os.stat(target_path).st_mtime
|
4148
|
-
)
|
4149
|
-
if need_copy:
|
4150
|
-
filesystem.mkdir_exists_ok(os.path.dirname(target_path))
|
4151
|
-
# We use copy2, which preserves file metadata including modified
|
4152
|
-
# time (which we use above to check whether we should do the copy).
|
4153
|
-
shutil.copy2(cache_path, target_path)
|
4154
|
-
return target_path
|
4138
|
+
raise NotImplementedError()
|
4155
4139
|
|
4156
4140
|
def download(self, root=None):
|
4157
4141
|
root = root or self._parent_artifact._default_root()
|
4142
|
+
dest_path = os.path.join(root, self.name)
|
4143
|
+
|
4158
4144
|
self._parent_artifact._add_download_root(root)
|
4159
4145
|
manifest = self._parent_artifact._load_manifest()
|
4146
|
+
|
4147
|
+
# Skip checking the cache (and possibly downloading) if the file already exists
|
4148
|
+
# and has the digest we're expecting.
|
4149
|
+
entry = manifest.entries[self.name]
|
4150
|
+
if os.path.exists(dest_path) and entry.digest == md5_file_b64(dest_path):
|
4151
|
+
return dest_path
|
4152
|
+
|
4160
4153
|
if self.ref is not None:
|
4161
|
-
cache_path = manifest.storage_policy.load_reference(
|
4162
|
-
manifest.entries[self.name],
|
4163
|
-
local=True,
|
4164
|
-
)
|
4154
|
+
cache_path = manifest.storage_policy.load_reference(entry, local=True)
|
4165
4155
|
else:
|
4166
|
-
cache_path = manifest.storage_policy.load_file(
|
4167
|
-
self._parent_artifact, manifest.entries[self.name]
|
4168
|
-
)
|
4156
|
+
cache_path = manifest.storage_policy.load_file(self._parent_artifact, entry)
|
4169
4157
|
|
4170
|
-
return
|
4158
|
+
return filesystem.copy_or_overwrite_changed(cache_path, dest_path)
|
4171
4159
|
|
4172
4160
|
def ref_target(self):
|
4173
4161
|
manifest = self._parent_artifact._load_manifest()
|
@@ -4224,8 +4212,7 @@ class _ArtifactDownloadLogger:
|
|
4224
4212
|
|
4225
4213
|
|
4226
4214
|
class Artifact(artifacts.Artifact):
|
4227
|
-
"""
|
4228
|
-
A wandb Artifact.
|
4215
|
+
"""A wandb Artifact.
|
4229
4216
|
|
4230
4217
|
An artifact that has been logged, including all its attributes, links to the runs
|
4231
4218
|
that use it, and a link to the run that logged it.
|
@@ -4350,7 +4337,7 @@ class Artifact(artifacts.Artifact):
|
|
4350
4337
|
with requests.get(index_file_url) as req:
|
4351
4338
|
req.raise_for_status()
|
4352
4339
|
artifact._manifest = artifacts.ArtifactManifest.from_manifest_json(
|
4353
|
-
|
4340
|
+
json.loads(util.ensure_text(req.content))
|
4354
4341
|
)
|
4355
4342
|
|
4356
4343
|
artifact._load_dependent_manifests()
|
@@ -4366,6 +4353,19 @@ class Artifact(artifacts.Artifact):
|
|
4366
4353
|
self._attrs = attrs
|
4367
4354
|
if self._attrs is None:
|
4368
4355
|
self._load()
|
4356
|
+
|
4357
|
+
# The entity and project above are taken from the passed-in artifact version path
|
4358
|
+
# so if the user is pulling an artifact version from an artifact portfolio, the entity/project
|
4359
|
+
# of that portfolio may be different than the birth entity/project of the artifact version.
|
4360
|
+
self._birth_project = (
|
4361
|
+
self._attrs.get("artifactType", {}).get("project", {}).get("name")
|
4362
|
+
)
|
4363
|
+
self._birth_entity = (
|
4364
|
+
self._attrs.get("artifactType", {})
|
4365
|
+
.get("project", {})
|
4366
|
+
.get("entity", {})
|
4367
|
+
.get("name")
|
4368
|
+
)
|
4369
4369
|
self._metadata = json.loads(self._attrs.get("metadata") or "{}")
|
4370
4370
|
self._description = self._attrs.get("description", None)
|
4371
4371
|
self._sequence_name = self._attrs["artifactSequence"]["name"]
|
@@ -4395,19 +4395,17 @@ class Artifact(artifacts.Artifact):
|
|
4395
4395
|
|
4396
4396
|
@property
|
4397
4397
|
def source_version(self):
|
4398
|
-
"""
|
4399
|
-
|
4400
|
-
|
4401
|
-
a string with the format "v{number}".
|
4398
|
+
"""The artifact's version index under its parent artifact collection.
|
4399
|
+
|
4400
|
+
A string with the format "v{number}".
|
4402
4401
|
"""
|
4403
4402
|
return f"v{self._sequence_version_index}"
|
4404
4403
|
|
4405
4404
|
@property
|
4406
4405
|
def version(self):
|
4407
|
-
"""
|
4408
|
-
|
4409
|
-
|
4410
|
-
a string with the format "v{number}".
|
4406
|
+
"""The artifact's version index under the given artifact collection.
|
4407
|
+
|
4408
|
+
A string with the format "v{number}".
|
4411
4409
|
"""
|
4412
4410
|
for a in self._attrs["aliases"]:
|
4413
4411
|
if a[
|
@@ -4452,18 +4450,12 @@ class Artifact(artifacts.Artifact):
|
|
4452
4450
|
|
4453
4451
|
@property
|
4454
4452
|
def created_at(self):
|
4455
|
-
"""
|
4456
|
-
Returns:
|
4457
|
-
(datetime): The time at which the artifact was created.
|
4458
|
-
"""
|
4453
|
+
"""The time at which the artifact was created."""
|
4459
4454
|
return self._attrs["createdAt"]
|
4460
4455
|
|
4461
4456
|
@property
|
4462
4457
|
def updated_at(self):
|
4463
|
-
"""
|
4464
|
-
Returns:
|
4465
|
-
(datetime): The time at which the artifact was last updated.
|
4466
|
-
"""
|
4458
|
+
"""The time at which the artifact was last updated."""
|
4467
4459
|
return self._attrs["updatedAt"] or self._attrs["createdAt"]
|
4468
4460
|
|
4469
4461
|
@property
|
@@ -4490,8 +4482,7 @@ class Artifact(artifacts.Artifact):
|
|
4490
4482
|
|
4491
4483
|
@property
|
4492
4484
|
def aliases(self):
|
4493
|
-
"""
|
4494
|
-
The aliases associated with this artifact.
|
4485
|
+
"""The aliases associated with this artifact.
|
4495
4486
|
|
4496
4487
|
Returns:
|
4497
4488
|
List[str]: The aliases associated with this artifact.
|
@@ -4510,7 +4501,7 @@ class Artifact(artifacts.Artifact):
|
|
4510
4501
|
|
4511
4502
|
@staticmethod
|
4512
4503
|
def expected_type(client, name, entity_name, project_name):
|
4513
|
-
"""Returns the expected type for a given artifact name and project"""
|
4504
|
+
"""Returns the expected type for a given artifact name and project."""
|
4514
4505
|
query = gql(
|
4515
4506
|
"""
|
4516
4507
|
query ArtifactType(
|
@@ -4604,8 +4595,7 @@ class Artifact(artifacts.Artifact):
|
|
4604
4595
|
|
4605
4596
|
@normalize_exceptions
|
4606
4597
|
def delete(self, delete_aliases=False):
|
4607
|
-
"""
|
4608
|
-
Delete an artifact and its files.
|
4598
|
+
"""Delete an artifact and its files.
|
4609
4599
|
|
4610
4600
|
Examples:
|
4611
4601
|
Delete all the "model" artifacts a run has logged:
|
@@ -4660,17 +4650,15 @@ class Artifact(artifacts.Artifact):
|
|
4660
4650
|
raise ValueError("Cannot add files to an artifact once it has been saved")
|
4661
4651
|
|
4662
4652
|
def _add_download_root(self, dir_path):
|
4663
|
-
"""
|
4664
|
-
artifact treated as a root"""
|
4653
|
+
"""Make `dir_path` a root directory for this artifact."""
|
4665
4654
|
self._download_roots.add(os.path.abspath(dir_path))
|
4666
4655
|
|
4667
4656
|
def _is_download_root(self, dir_path):
|
4668
|
-
"""
|
4669
|
-
treated as a root for downloading"""
|
4657
|
+
"""Determine if `dir_path` is a root directory for this artifact."""
|
4670
4658
|
return dir_path in self._download_roots
|
4671
4659
|
|
4672
4660
|
def _local_path_to_name(self, file_path):
|
4673
|
-
"""
|
4661
|
+
"""Convert a local file path to a path entry in the artifact."""
|
4674
4662
|
abs_file_path = os.path.abspath(file_path)
|
4675
4663
|
abs_file_parts = abs_file_path.split(os.sep)
|
4676
4664
|
for i in range(len(abs_file_parts) + 1):
|
@@ -4679,10 +4667,11 @@ class Artifact(artifacts.Artifact):
|
|
4679
4667
|
return None
|
4680
4668
|
|
4681
4669
|
def _get_obj_entry(self, name):
|
4682
|
-
"""
|
4683
|
-
|
4684
|
-
|
4685
|
-
|
4670
|
+
"""Return an object entry by name, handling any type suffixes.
|
4671
|
+
|
4672
|
+
When objects are added with `.add(obj, name)`, the name is typically changed to
|
4673
|
+
include the suffix of the object type when serializing to JSON. So we need to be
|
4674
|
+
able to resolve a name, without tasking the user with appending .THING.json.
|
4686
4675
|
This method returns an entry if it exists by a suffixed name.
|
4687
4676
|
|
4688
4677
|
Args:
|
@@ -4831,7 +4820,7 @@ class Artifact(artifacts.Artifact):
|
|
4831
4820
|
print("Warning: skipped verification of %s refs" % ref_count)
|
4832
4821
|
|
4833
4822
|
def file(self, root=None):
|
4834
|
-
"""Download a single file artifact to dir specified by the root
|
4823
|
+
"""Download a single file artifact to dir specified by the root.
|
4835
4824
|
|
4836
4825
|
Arguments:
|
4837
4826
|
root: (str, optional) The root directory in which to place the file. Defaults to './artifacts/self.name/'.
|
@@ -4839,7 +4828,6 @@ class Artifact(artifacts.Artifact):
|
|
4839
4828
|
Returns:
|
4840
4829
|
(str): The full path of the downloaded file.
|
4841
4830
|
"""
|
4842
|
-
|
4843
4831
|
if root is None:
|
4844
4832
|
root = os.path.join(".", "artifacts", self.name)
|
4845
4833
|
|
@@ -4878,9 +4866,7 @@ class Artifact(artifacts.Artifact):
|
|
4878
4866
|
|
4879
4867
|
@normalize_exceptions
|
4880
4868
|
def save(self):
|
4881
|
-
"""
|
4882
|
-
Persists artifact changes to the wandb backend.
|
4883
|
-
"""
|
4869
|
+
"""Persists artifact changes to the wandb backend."""
|
4884
4870
|
mutation = gql(
|
4885
4871
|
"""
|
4886
4872
|
mutation updateArtifact(
|
@@ -4948,11 +4934,10 @@ class Artifact(artifacts.Artifact):
|
|
4948
4934
|
|
4949
4935
|
@normalize_exceptions
|
4950
4936
|
def _save_alias_changes(self):
|
4951
|
-
"""
|
4952
|
-
Convenience function called by artifact.save() to persist alias changes
|
4953
|
-
on this artifact to the wandb backend.
|
4954
|
-
"""
|
4937
|
+
"""Persist alias changes on this artifact to the wandb backend.
|
4955
4938
|
|
4939
|
+
Called by artifact.save().
|
4940
|
+
"""
|
4956
4941
|
aliases_to_add = set(self._aliases) - set(self._frozen_aliases)
|
4957
4942
|
aliases_to_remove = set(self._frozen_aliases) - set(self._aliases)
|
4958
4943
|
|
@@ -5152,7 +5137,7 @@ class Artifact(artifacts.Artifact):
|
|
5152
5137
|
with requests.get(index_file_url) as req:
|
5153
5138
|
req.raise_for_status()
|
5154
5139
|
self._manifest = artifacts.ArtifactManifest.from_manifest_json(
|
5155
|
-
|
5140
|
+
json.loads(util.ensure_text(req.content))
|
5156
5141
|
)
|
5157
5142
|
|
5158
5143
|
self._load_dependent_manifests()
|
@@ -5160,7 +5145,7 @@ class Artifact(artifacts.Artifact):
|
|
5160
5145
|
return self._manifest
|
5161
5146
|
|
5162
5147
|
def _load_dependent_manifests(self):
|
5163
|
-
"""
|
5148
|
+
"""Interrogate entries and ensure we have loaded their manifests."""
|
5164
5149
|
# Make sure dependencies are avail
|
5165
5150
|
for entry_key in self._manifest.entries:
|
5166
5151
|
entry = self._manifest.entries[entry_key]
|
@@ -5172,19 +5157,19 @@ class Artifact(artifacts.Artifact):
|
|
5172
5157
|
|
5173
5158
|
@staticmethod
|
5174
5159
|
def _manifest_entry_is_artifact_reference(entry):
|
5175
|
-
"""
|
5160
|
+
"""Determine if an ArtifactManifestEntry is an artifact reference."""
|
5176
5161
|
return (
|
5177
5162
|
entry.ref is not None
|
5178
5163
|
and urllib.parse.urlparse(entry.ref).scheme == "wandb-artifact"
|
5179
5164
|
)
|
5180
5165
|
|
5181
5166
|
def _get_ref_artifact_from_entry(self, entry):
|
5182
|
-
"""Helper function returns the referenced artifact from an entry"""
|
5167
|
+
"""Helper function returns the referenced artifact from an entry."""
|
5183
5168
|
artifact_id = util.host_from_path(entry.ref)
|
5184
5169
|
return Artifact.from_id(hex_to_b64_id(artifact_id), self.client)
|
5185
5170
|
|
5186
5171
|
def used_by(self):
|
5187
|
-
"""
|
5172
|
+
"""Retrieve the runs which use this artifact directly.
|
5188
5173
|
|
5189
5174
|
Returns:
|
5190
5175
|
[Run]: a list of Run objects which use this artifact
|
@@ -5231,7 +5216,7 @@ class Artifact(artifacts.Artifact):
|
|
5231
5216
|
return runs
|
5232
5217
|
|
5233
5218
|
def logged_by(self):
|
5234
|
-
"""
|
5219
|
+
"""Retrieve the run which logged this artifact.
|
5235
5220
|
|
5236
5221
|
Returns:
|
5237
5222
|
Run: Run object which logged this artifact
|
@@ -5277,7 +5262,8 @@ class Artifact(artifacts.Artifact):
|
|
5277
5262
|
|
5278
5263
|
class ArtifactVersions(Paginator):
|
5279
5264
|
"""An iterable collection of artifact versions associated with a project and optional filter.
|
5280
|
-
|
5265
|
+
|
5266
|
+
This is generally used indirectly via the `Api`.artifact_versions method.
|
5281
5267
|
"""
|
5282
5268
|
|
5283
5269
|
def __init__(
|
@@ -5419,8 +5405,8 @@ class ArtifactFiles(Paginator):
|
|
5419
5405
|
):
|
5420
5406
|
self.artifact = artifact
|
5421
5407
|
variables = {
|
5422
|
-
"entityName": artifact.
|
5423
|
-
"projectName": artifact.
|
5408
|
+
"entityName": artifact._birth_entity,
|
5409
|
+
"projectName": artifact._birth_project,
|
5424
5410
|
"artifactTypeName": artifact.type,
|
5425
5411
|
"artifactName": artifact.name,
|
5426
5412
|
"fileNames": names,
|
@@ -5473,7 +5459,6 @@ class ArtifactFiles(Paginator):
|
|
5473
5459
|
|
5474
5460
|
|
5475
5461
|
class Job:
|
5476
|
-
|
5477
5462
|
_name: str
|
5478
5463
|
_input_types: Type
|
5479
5464
|
_output_types: Type
|
@@ -5577,7 +5562,6 @@ class Job:
|
|
5577
5562
|
queue=None,
|
5578
5563
|
resource="local-container",
|
5579
5564
|
resource_args=None,
|
5580
|
-
cuda=False,
|
5581
5565
|
project_queue=None,
|
5582
5566
|
):
|
5583
5567
|
from wandb.sdk.launch import launch_add
|
@@ -5604,6 +5588,5 @@ class Job:
|
|
5604
5588
|
resource=resource,
|
5605
5589
|
project_queue=project_queue,
|
5606
5590
|
resource_args=resource_args,
|
5607
|
-
cuda=cuda,
|
5608
5591
|
)
|
5609
5592
|
return queued_run
|