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/data_types.py
CHANGED
@@ -148,7 +148,7 @@ def _json_helper(val, artifact):
|
|
148
148
|
|
149
149
|
|
150
150
|
class Table(Media):
|
151
|
-
"""The Table class
|
151
|
+
"""The Table class used to display and analyze tabular data.
|
152
152
|
|
153
153
|
Unlike traditional spreadsheets, Tables support numerous types of data:
|
154
154
|
scalar values, strings, numpy arrays, and most subclasses of `wandb.data_types.Media`.
|
@@ -257,7 +257,10 @@ class Table(Media):
|
|
257
257
|
optional=True,
|
258
258
|
allow_mixed_types=False,
|
259
259
|
):
|
260
|
-
"""
|
260
|
+
"""Initialize a Table object.
|
261
|
+
|
262
|
+
Rows is kept for legacy reasons, we use data to mimic the Pandas api.
|
263
|
+
"""
|
261
264
|
super().__init__()
|
262
265
|
self._pk_col = None
|
263
266
|
self._fk_cols = set()
|
@@ -344,7 +347,7 @@ class Table(Media):
|
|
344
347
|
self.cast(col_name, dt, opt)
|
345
348
|
|
346
349
|
def cast(self, col_name, dtype, optional=False):
|
347
|
-
"""
|
350
|
+
"""Cast a column to a specific type.
|
348
351
|
|
349
352
|
Arguments:
|
350
353
|
col_name: (str) - name of the column to cast
|
@@ -445,12 +448,15 @@ class Table(Media):
|
|
445
448
|
return self._eq_debug(other)
|
446
449
|
|
447
450
|
def add_row(self, *row):
|
448
|
-
"""
|
451
|
+
"""Deprecated: use add_data instead."""
|
449
452
|
logging.warning("add_row is deprecated, use add_data")
|
450
453
|
self.add_data(*row)
|
451
454
|
|
452
455
|
def add_data(self, *data):
|
453
|
-
"""Add a row of data to the table.
|
456
|
+
"""Add a row of data to the table.
|
457
|
+
|
458
|
+
Argument length should match column length.
|
459
|
+
"""
|
454
460
|
if len(data) != len(self.columns):
|
455
461
|
raise ValueError(
|
456
462
|
"This table expects {} columns: {}, found {}".format(
|
@@ -482,8 +488,11 @@ class Table(Media):
|
|
482
488
|
self._update_keys(force_last=True)
|
483
489
|
|
484
490
|
def _get_updated_result_type(self, row):
|
485
|
-
"""
|
486
|
-
|
491
|
+
"""Return an updated result type based on incoming row.
|
492
|
+
|
493
|
+
Raises:
|
494
|
+
TypeError: if the assignment is invalid.
|
495
|
+
"""
|
487
496
|
incoming_row_dict = {
|
488
497
|
col_key: row[ndx] for ndx, col_key in enumerate(self.columns)
|
489
498
|
}
|
@@ -695,14 +704,15 @@ class Table(Media):
|
|
695
704
|
return json_dict
|
696
705
|
|
697
706
|
def iterrows(self):
|
698
|
-
"""Iterate over rows as (ndx, row)
|
699
|
-
|
707
|
+
"""Iterate over rows as (ndx, row).
|
708
|
+
|
709
|
+
Yields:
|
700
710
|
------
|
701
711
|
index : int
|
702
712
|
The index of the row. Using this value in other WandB tables
|
703
713
|
will automatically build a relationship between the tables
|
704
714
|
row : List[any]
|
705
|
-
The data of the row
|
715
|
+
The data of the row.
|
706
716
|
"""
|
707
717
|
for ndx in range(len(self.data)):
|
708
718
|
index = _TableIndex(ndx)
|
@@ -721,13 +731,14 @@ class Table(Media):
|
|
721
731
|
self.cast(col_name, _ForeignKeyType(table, table_col))
|
722
732
|
|
723
733
|
def _update_keys(self, force_last=False):
|
724
|
-
"""
|
725
|
-
|
726
|
-
the last update, we wrap the data
|
734
|
+
"""Update the known key-like columns based on the current column types.
|
735
|
+
|
736
|
+
If the state has been updated since the last update, we wrap the data
|
737
|
+
appropriately in the Key classes.
|
727
738
|
|
728
739
|
Arguments:
|
729
|
-
|
730
|
-
|
740
|
+
force_last: (bool) Determines wrapping the last column of data even if there
|
741
|
+
are no key updates.
|
731
742
|
"""
|
732
743
|
_pk_col = None
|
733
744
|
_fk_cols = set()
|
@@ -767,7 +778,7 @@ class Table(Media):
|
|
767
778
|
self._apply_key_updates(not has_update)
|
768
779
|
|
769
780
|
def _apply_key_updates(self, only_last=False):
|
770
|
-
"""Appropriately
|
781
|
+
"""Appropriately wrap the underlying data in special key classes.
|
771
782
|
|
772
783
|
Arguments:
|
773
784
|
only_last: only apply the updates to the last row (used for performance when
|
@@ -818,7 +829,7 @@ class Table(Media):
|
|
818
829
|
def add_column(self, name, data, optional=False):
|
819
830
|
"""Add a column of data to the table.
|
820
831
|
|
821
|
-
Arguments
|
832
|
+
Arguments:
|
822
833
|
name: (str) - the unique name of the column
|
823
834
|
data: (list | np.array) - a column of homogenous data
|
824
835
|
optional: (bool) - if null-like values are permitted
|
@@ -857,9 +868,9 @@ class Table(Media):
|
|
857
868
|
raise err
|
858
869
|
|
859
870
|
def get_column(self, name, convert_to=None):
|
860
|
-
"""
|
871
|
+
"""Retrieve a column of data from the table.
|
861
872
|
|
862
|
-
Arguments
|
873
|
+
Arguments:
|
863
874
|
name: (str) - the name of the column
|
864
875
|
convert_to: (str, optional)
|
865
876
|
- "numpy": will convert the underlying data to numpy object
|
@@ -882,7 +893,7 @@ class Table(Media):
|
|
882
893
|
return col
|
883
894
|
|
884
895
|
def get_index(self):
|
885
|
-
"""
|
896
|
+
"""Return an array of row indexes for use in other tables to create links."""
|
886
897
|
ndxs = []
|
887
898
|
for ndx in range(len(self.data)):
|
888
899
|
index = _TableIndex(ndx)
|
@@ -891,14 +902,14 @@ class Table(Media):
|
|
891
902
|
return ndxs
|
892
903
|
|
893
904
|
def index_ref(self, index):
|
894
|
-
"""Get a reference to a particular row index in the table"""
|
905
|
+
"""Get a reference to a particular row index in the table."""
|
895
906
|
assert index < len(self.data)
|
896
907
|
_index = _TableIndex(index)
|
897
908
|
_index.set_table(self)
|
898
909
|
return _index
|
899
910
|
|
900
911
|
def add_computed_columns(self, fn):
|
901
|
-
"""
|
912
|
+
"""Add one or more computed columns based on existing data.
|
902
913
|
|
903
914
|
Args:
|
904
915
|
fn: A function which accepts one or two parameters, ndx (int) and row (dict),
|
@@ -923,7 +934,7 @@ class Table(Media):
|
|
923
934
|
|
924
935
|
|
925
936
|
class _PartitionTablePartEntry:
|
926
|
-
"""Helper class for PartitionTable to track its parts"""
|
937
|
+
"""Helper class for PartitionTable to track its parts."""
|
927
938
|
|
928
939
|
def __init__(self, entry, source_artifact):
|
929
940
|
self.entry = entry
|
@@ -940,17 +951,18 @@ class _PartitionTablePartEntry:
|
|
940
951
|
|
941
952
|
|
942
953
|
class PartitionedTable(Media):
|
943
|
-
"""
|
944
|
-
|
945
|
-
is designed to point to a directory within an artifact.
|
954
|
+
"""A table which is composed of multiple sub-tables.
|
955
|
+
|
956
|
+
Currently, PartitionedTable is designed to point to a directory within an artifact.
|
946
957
|
"""
|
947
958
|
|
948
959
|
_log_type = "partitioned-table"
|
949
960
|
|
950
961
|
def __init__(self, parts_path):
|
951
|
-
"""
|
962
|
+
"""Initialize a PartitionedTable.
|
963
|
+
|
952
964
|
Args:
|
953
|
-
parts_path (str): path to a directory of tables in the artifact
|
965
|
+
parts_path (str): path to a directory of tables in the artifact.
|
954
966
|
"""
|
955
967
|
super().__init__()
|
956
968
|
self.parts_path = parts_path
|
@@ -982,13 +994,14 @@ class PartitionedTable(Media):
|
|
982
994
|
return instance
|
983
995
|
|
984
996
|
def iterrows(self):
|
985
|
-
"""Iterate over rows as (ndx, row)
|
986
|
-
|
997
|
+
"""Iterate over rows as (ndx, row).
|
998
|
+
|
999
|
+
Yields:
|
987
1000
|
------
|
988
1001
|
index : int
|
989
1002
|
The index of the row.
|
990
1003
|
row : List[any]
|
991
|
-
The data of the row
|
1004
|
+
The data of the row.
|
992
1005
|
"""
|
993
1006
|
columns = None
|
994
1007
|
ndx = 0
|
@@ -1024,8 +1037,7 @@ class PartitionedTable(Media):
|
|
1024
1037
|
|
1025
1038
|
|
1026
1039
|
class Audio(BatchableMedia):
|
1027
|
-
"""
|
1028
|
-
Wandb class for audio clips.
|
1040
|
+
"""Wandb class for audio clips.
|
1029
1041
|
|
1030
1042
|
Arguments:
|
1031
1043
|
data_or_path: (string or numpy array) A path to an audio file
|
@@ -1038,7 +1050,7 @@ class Audio(BatchableMedia):
|
|
1038
1050
|
_log_type = "audio-file"
|
1039
1051
|
|
1040
1052
|
def __init__(self, data_or_path, sample_rate=None, caption=None):
|
1041
|
-
"""
|
1053
|
+
"""Accept a path to an audio file or a numpy array of audio data."""
|
1042
1054
|
super().__init__()
|
1043
1055
|
self._duration = None
|
1044
1056
|
self._sample_rate = sample_rate
|
@@ -1172,7 +1184,7 @@ class Audio(BatchableMedia):
|
|
1172
1184
|
|
1173
1185
|
|
1174
1186
|
class JoinedTable(Media):
|
1175
|
-
"""
|
1187
|
+
"""Join two tables for visualization in the Artifact UI.
|
1176
1188
|
|
1177
1189
|
Arguments:
|
1178
1190
|
table1 (str, wandb.Table, ArtifactManifestEntry):
|
@@ -1227,7 +1239,7 @@ class JoinedTable(Media):
|
|
1227
1239
|
|
1228
1240
|
@staticmethod
|
1229
1241
|
def _validate_table_input(table):
|
1230
|
-
"""Helper method to validate that the table input is one of the 3 supported types"""
|
1242
|
+
"""Helper method to validate that the table input is one of the 3 supported types."""
|
1231
1243
|
return (
|
1232
1244
|
(type(table) == str and table.endswith(".table.json"))
|
1233
1245
|
or isinstance(table, Table)
|
@@ -1236,7 +1248,7 @@ class JoinedTable(Media):
|
|
1236
1248
|
)
|
1237
1249
|
|
1238
1250
|
def _ensure_table_in_artifact(self, table, artifact, table_ndx):
|
1239
|
-
"""Helper method to add the table to the incoming artifact. Returns the path"""
|
1251
|
+
"""Helper method to add the table to the incoming artifact. Returns the path."""
|
1240
1252
|
if isinstance(table, Table) or isinstance(table, PartitionedTable):
|
1241
1253
|
table_name = f"t{table_ndx}_{str(id(self))}"
|
1242
1254
|
if (
|
@@ -1310,8 +1322,7 @@ class JoinedTable(Media):
|
|
1310
1322
|
|
1311
1323
|
|
1312
1324
|
class Bokeh(Media):
|
1313
|
-
"""
|
1314
|
-
Wandb class for Bokeh plots.
|
1325
|
+
"""Wandb class for Bokeh plots.
|
1315
1326
|
|
1316
1327
|
Arguments:
|
1317
1328
|
val: Bokeh plot
|
@@ -1373,7 +1384,7 @@ def _nest(thing):
|
|
1373
1384
|
|
1374
1385
|
|
1375
1386
|
class Graph(Media):
|
1376
|
-
"""Wandb class for graphs
|
1387
|
+
"""Wandb class for graphs.
|
1377
1388
|
|
1378
1389
|
This class is typically used for saving and diplaying neural net models. It
|
1379
1390
|
represents the graph as an array of nodes and edges. The nodes can have
|
@@ -1537,9 +1548,7 @@ class Graph(Media):
|
|
1537
1548
|
|
1538
1549
|
|
1539
1550
|
class Node(WBValue):
|
1540
|
-
"""
|
1541
|
-
Node used in `Graph`
|
1542
|
-
"""
|
1551
|
+
"""Node used in `Graph`."""
|
1543
1552
|
|
1544
1553
|
def __init__(
|
1545
1554
|
self,
|
@@ -1589,7 +1598,7 @@ class Node(WBValue):
|
|
1589
1598
|
|
1590
1599
|
@property
|
1591
1600
|
def id(self):
|
1592
|
-
"""Must be unique in the graph"""
|
1601
|
+
"""Must be unique in the graph."""
|
1593
1602
|
return self._attributes.get("id")
|
1594
1603
|
|
1595
1604
|
@id.setter
|
@@ -1599,7 +1608,7 @@ class Node(WBValue):
|
|
1599
1608
|
|
1600
1609
|
@property
|
1601
1610
|
def name(self):
|
1602
|
-
"""Usually the type of layer or sublayer"""
|
1611
|
+
"""Usually the type of layer or sublayer."""
|
1603
1612
|
return self._attributes.get("name")
|
1604
1613
|
|
1605
1614
|
@name.setter
|
@@ -1609,7 +1618,7 @@ class Node(WBValue):
|
|
1609
1618
|
|
1610
1619
|
@property
|
1611
1620
|
def class_name(self):
|
1612
|
-
"""Usually the type of layer or sublayer"""
|
1621
|
+
"""Usually the type of layer or sublayer."""
|
1613
1622
|
return self._attributes.get("class_name")
|
1614
1623
|
|
1615
1624
|
@class_name.setter
|
@@ -1641,7 +1650,7 @@ class Node(WBValue):
|
|
1641
1650
|
|
1642
1651
|
@size.setter
|
1643
1652
|
def size(self, val):
|
1644
|
-
"""Tensor size"""
|
1653
|
+
"""Tensor size."""
|
1645
1654
|
self._attributes["size"] = tuple(val)
|
1646
1655
|
return val
|
1647
1656
|
|
@@ -1651,7 +1660,7 @@ class Node(WBValue):
|
|
1651
1660
|
|
1652
1661
|
@output_shape.setter
|
1653
1662
|
def output_shape(self, val):
|
1654
|
-
"""Tensor output_shape"""
|
1663
|
+
"""Tensor output_shape."""
|
1655
1664
|
self._attributes["output_shape"] = val
|
1656
1665
|
return val
|
1657
1666
|
|
@@ -1661,7 +1670,7 @@ class Node(WBValue):
|
|
1661
1670
|
|
1662
1671
|
@is_output.setter
|
1663
1672
|
def is_output(self, val):
|
1664
|
-
"""Tensor is_output"""
|
1673
|
+
"""Tensor is_output."""
|
1665
1674
|
self._attributes["is_output"] = val
|
1666
1675
|
return val
|
1667
1676
|
|
@@ -1671,7 +1680,7 @@ class Node(WBValue):
|
|
1671
1680
|
|
1672
1681
|
@num_parameters.setter
|
1673
1682
|
def num_parameters(self, val):
|
1674
|
-
"""Tensor num_parameters"""
|
1683
|
+
"""Tensor num_parameters."""
|
1675
1684
|
self._attributes["num_parameters"] = val
|
1676
1685
|
return val
|
1677
1686
|
|
@@ -1681,7 +1690,7 @@ class Node(WBValue):
|
|
1681
1690
|
|
1682
1691
|
@child_parameters.setter
|
1683
1692
|
def child_parameters(self, val):
|
1684
|
-
"""Tensor child_parameters"""
|
1693
|
+
"""Tensor child_parameters."""
|
1685
1694
|
self._attributes["child_parameters"] = val
|
1686
1695
|
return val
|
1687
1696
|
|
@@ -1691,7 +1700,7 @@ class Node(WBValue):
|
|
1691
1700
|
|
1692
1701
|
@is_constant.setter
|
1693
1702
|
def is_constant(self, val):
|
1694
|
-
"""Tensor is_constant"""
|
1703
|
+
"""Tensor is_constant."""
|
1695
1704
|
self._attributes["is_constant"] = val
|
1696
1705
|
return val
|
1697
1706
|
|
@@ -1714,9 +1723,7 @@ class Node(WBValue):
|
|
1714
1723
|
|
1715
1724
|
|
1716
1725
|
class Edge(WBValue):
|
1717
|
-
"""
|
1718
|
-
Edge used in `Graph`
|
1719
|
-
"""
|
1726
|
+
"""Edge used in `Graph`."""
|
1720
1727
|
|
1721
1728
|
def __init__(self, from_node, to_node):
|
1722
1729
|
self._attributes = {}
|
@@ -1736,7 +1743,7 @@ class Edge(WBValue):
|
|
1736
1743
|
|
1737
1744
|
@property
|
1738
1745
|
def name(self):
|
1739
|
-
"""Optional, not necessarily unique"""
|
1746
|
+
"""Optional, not necessarily unique."""
|
1740
1747
|
return self._attributes.get("name")
|
1741
1748
|
|
1742
1749
|
@name.setter
|
wandb/docker/__init__.py
CHANGED
@@ -8,7 +8,40 @@ import requests
|
|
8
8
|
from dockerpycreds.utils import find_executable # type: ignore
|
9
9
|
|
10
10
|
from wandb.docker import auth, www_authenticate
|
11
|
-
from wandb.errors import
|
11
|
+
from wandb.errors import Error
|
12
|
+
|
13
|
+
|
14
|
+
class DockerError(Error):
|
15
|
+
"""Raised when attempting to execute a docker command."""
|
16
|
+
|
17
|
+
def __init__(
|
18
|
+
self,
|
19
|
+
command_launched: List[str],
|
20
|
+
return_code: int,
|
21
|
+
stdout: Optional[bytes] = None,
|
22
|
+
stderr: Optional[bytes] = None,
|
23
|
+
) -> None:
|
24
|
+
command_launched_str = " ".join(command_launched)
|
25
|
+
error_msg = (
|
26
|
+
f"The docker command executed was `{command_launched_str}`.\n"
|
27
|
+
f"It returned with code {return_code}\n"
|
28
|
+
)
|
29
|
+
if stdout is not None:
|
30
|
+
error_msg += f"The content of stdout is '{stdout.decode()}'\n"
|
31
|
+
else:
|
32
|
+
error_msg += (
|
33
|
+
"The content of stdout can be found above the "
|
34
|
+
"stacktrace (it wasn't captured).\n"
|
35
|
+
)
|
36
|
+
if stderr is not None:
|
37
|
+
error_msg += f"The content of stderr is '{stderr.decode()}'\n"
|
38
|
+
else:
|
39
|
+
error_msg += (
|
40
|
+
"The content of stderr can be found above the "
|
41
|
+
"stacktrace (it wasn't captured)."
|
42
|
+
)
|
43
|
+
super().__init__(error_msg)
|
44
|
+
|
12
45
|
|
13
46
|
entrypoint = os.path.join(
|
14
47
|
os.path.dirname(os.path.abspath(__file__)), "wandb-entrypoint.sh"
|
@@ -18,9 +51,10 @@ log = logging.getLogger(__name__)
|
|
18
51
|
|
19
52
|
|
20
53
|
def shell(cmd: List[str]) -> Optional[str]:
|
21
|
-
"""Simple wrapper for calling docker
|
54
|
+
"""Simple wrapper for calling docker,.
|
22
55
|
|
23
|
-
returning None on error and the output on success
|
56
|
+
returning None on error and the output on success
|
57
|
+
"""
|
24
58
|
try:
|
25
59
|
return (
|
26
60
|
subprocess.check_output(["docker"] + cmd, stderr=subprocess.STDOUT)
|
@@ -36,7 +70,7 @@ _buildx_installed = None
|
|
36
70
|
|
37
71
|
|
38
72
|
def is_buildx_installed() -> bool:
|
39
|
-
"""
|
73
|
+
"""Return `True` if docker buildx is installed and working."""
|
40
74
|
global _buildx_installed
|
41
75
|
if _buildx_installed is not None:
|
42
76
|
return _buildx_installed # type: ignore
|
@@ -53,12 +87,40 @@ def build(tags: List[str], file: str, context_path: str) -> str:
|
|
53
87
|
build_tags = []
|
54
88
|
for tag in tags:
|
55
89
|
build_tags += ["-t", tag]
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
capture_stdout=False,
|
90
|
+
args = ["docker"] + command + build_tags + ["-f", file, context_path]
|
91
|
+
stdout = run_command_live_output(
|
92
|
+
args,
|
60
93
|
)
|
61
|
-
return
|
94
|
+
return stdout
|
95
|
+
|
96
|
+
|
97
|
+
def run_command_live_output(args: List[Any]) -> str:
|
98
|
+
with subprocess.Popen(
|
99
|
+
args,
|
100
|
+
stdout=subprocess.PIPE,
|
101
|
+
stderr=subprocess.STDOUT,
|
102
|
+
universal_newlines=True,
|
103
|
+
bufsize=1,
|
104
|
+
) as process:
|
105
|
+
stdout = ""
|
106
|
+
while True:
|
107
|
+
chunk = os.read(process.stdout.fileno(), 4096) # type: ignore
|
108
|
+
if not chunk:
|
109
|
+
break
|
110
|
+
index = chunk.find(b"\r")
|
111
|
+
if index != -1:
|
112
|
+
print(chunk.decode(), end="")
|
113
|
+
else:
|
114
|
+
stdout += chunk.decode()
|
115
|
+
print(chunk.decode(), end="\r")
|
116
|
+
|
117
|
+
print(stdout)
|
118
|
+
|
119
|
+
return_code = process.wait()
|
120
|
+
if return_code != 0:
|
121
|
+
raise DockerError(args, return_code, stdout.encode())
|
122
|
+
|
123
|
+
return stdout
|
62
124
|
|
63
125
|
|
64
126
|
def run(
|
@@ -132,7 +194,7 @@ def parse(image_name: str) -> Tuple[str, str, str]:
|
|
132
194
|
|
133
195
|
|
134
196
|
def auth_token(registry: str, repo: str) -> Dict[str, str]:
|
135
|
-
"""
|
197
|
+
"""Make a request to the root of a v2 docker registry to get the auth url.
|
136
198
|
|
137
199
|
Always returns a dictionary, if there's no token key we couldn't authenticate
|
138
200
|
"""
|
@@ -175,7 +237,7 @@ def auth_token(registry: str, repo: str) -> Dict[str, str]:
|
|
175
237
|
|
176
238
|
|
177
239
|
def image_id_from_registry(image_name: str) -> Optional[str]:
|
178
|
-
"""Get the docker id from a public or private registry"""
|
240
|
+
"""Get the docker id from a public or private registry."""
|
179
241
|
registry, repository, tag = parse(image_name)
|
180
242
|
res = None
|
181
243
|
try:
|
@@ -199,7 +261,7 @@ def image_id_from_registry(image_name: str) -> Optional[str]:
|
|
199
261
|
|
200
262
|
|
201
263
|
def image_id(image_name: str) -> Optional[str]:
|
202
|
-
"""Retreve the image id from the local docker daemon or remote registry"""
|
264
|
+
"""Retreve the image id from the local docker daemon or remote registry."""
|
203
265
|
if "@sha256:" in image_name:
|
204
266
|
return image_name
|
205
267
|
else:
|
@@ -214,23 +276,23 @@ def image_id(image_name: str) -> Optional[str]:
|
|
214
276
|
|
215
277
|
|
216
278
|
def get_image_uid(image_name: str) -> int:
|
217
|
-
"""Retrieve the image default uid through brute force"""
|
279
|
+
"""Retrieve the image default uid through brute force."""
|
218
280
|
image_uid = shell(["run", image_name, "id", "-u"])
|
219
281
|
return int(image_uid) if image_uid else -1
|
220
282
|
|
221
283
|
|
222
284
|
def push(image: str, tag: str) -> Optional[str]:
|
223
|
-
"""Push an image to a remote registry"""
|
285
|
+
"""Push an image to a remote registry."""
|
224
286
|
return shell(["push", f"{image}:{tag}"])
|
225
287
|
|
226
288
|
|
227
289
|
def login(username: str, password: str, registry: str) -> Optional[str]:
|
228
|
-
"""Login to a registry"""
|
290
|
+
"""Login to a registry."""
|
229
291
|
return shell(["login", "--username", username, "--password", password, registry])
|
230
292
|
|
231
293
|
|
232
294
|
def tag(image_name: str, tag: str) -> Optional[str]:
|
233
|
-
"""Tag an image"""
|
295
|
+
"""Tag an image."""
|
234
296
|
return shell(["tag", image_name, tag])
|
235
297
|
|
236
298
|
|
wandb/docker/auth.py
CHANGED
@@ -19,8 +19,8 @@ log = logging.getLogger(__name__)
|
|
19
19
|
|
20
20
|
|
21
21
|
class DockerError(Exception):
|
22
|
-
"""
|
23
|
-
|
22
|
+
"""Base class from which all other exceptions inherit.
|
23
|
+
|
24
24
|
If you want to catch all errors that the Docker SDK might raise,
|
25
25
|
catch this base exception.
|
26
26
|
"""
|
@@ -67,9 +67,10 @@ def config_path_from_environment() -> Optional[str]:
|
|
67
67
|
|
68
68
|
|
69
69
|
def home_dir() -> str:
|
70
|
-
"""
|
71
|
-
|
72
|
-
client - use %USERPROFILE% on Windows,
|
70
|
+
"""Get the user's home directory.
|
71
|
+
|
72
|
+
Uses the same logic as the Docker Engine client - use %USERPROFILE% on Windows,
|
73
|
+
$HOME/getuid on POSIX.
|
73
74
|
"""
|
74
75
|
if IS_WINDOWS_PLATFORM:
|
75
76
|
return os.environ.get("USERPROFILE", "")
|
@@ -149,8 +150,8 @@ class AuthConfig(dict):
|
|
149
150
|
entries: Dict[str, Dict[str, Any]],
|
150
151
|
raise_on_error: bool = False,
|
151
152
|
) -> Dict[str, Dict[str, Any]]:
|
152
|
-
"""
|
153
|
-
|
153
|
+
"""Parse authentication entries.
|
154
|
+
|
154
155
|
Arguments:
|
155
156
|
entries: Dict of authentication entries.
|
156
157
|
raise_on_error: If set to true, an invalid format will raise
|
@@ -158,7 +159,6 @@ class AuthConfig(dict):
|
|
158
159
|
Returns:
|
159
160
|
Authentication registry.
|
160
161
|
"""
|
161
|
-
|
162
162
|
conf = {}
|
163
163
|
for registry, entry in entries.items():
|
164
164
|
if not isinstance(entry, dict):
|
@@ -210,14 +210,15 @@ class AuthConfig(dict):
|
|
210
210
|
config_dict: Optional[Dict[str, Any]],
|
211
211
|
credstore_env: Optional[Mapping] = None,
|
212
212
|
) -> "AuthConfig":
|
213
|
-
"""
|
214
|
-
|
215
|
-
|
213
|
+
"""Load authentication data from a Docker configuration file.
|
214
|
+
|
215
|
+
If the config_path is not passed in it looks for a configuration file in the
|
216
|
+
root directory.
|
217
|
+
|
216
218
|
Lookup priority:
|
217
219
|
explicit config_path parameter > DOCKER_CONFIG environment
|
218
|
-
variable > ~/.docker/config.json > ~/.dockercfg
|
220
|
+
variable > ~/.docker/config.json > ~/.dockercfg.
|
219
221
|
"""
|
220
|
-
|
221
222
|
if not config_dict:
|
222
223
|
config_file = find_config_file(config_path)
|
223
224
|
|
@@ -274,13 +275,12 @@ class AuthConfig(dict):
|
|
274
275
|
def resolve_authconfig(
|
275
276
|
self, registry: Optional[str] = None
|
276
277
|
) -> Optional[Dict[str, Any]]:
|
277
|
-
"""
|
278
|
-
Returns the authentication data from the given auth configuration for a
|
279
|
-
specific registry. As with the Docker client, legacy entries in the
|
280
|
-
config with full URLs are stripped down to hostnames before checking
|
281
|
-
for a match. Returns None if no match was found.
|
282
|
-
"""
|
278
|
+
"""Return the authentication data for a specific registry.
|
283
279
|
|
280
|
+
As with the Docker client, legacy entries in the config with full URLs are
|
281
|
+
stripped down to hostnames before checking for a match. Returns None if no match
|
282
|
+
was found.
|
283
|
+
"""
|
284
284
|
if self.creds_store or self.cred_helpers:
|
285
285
|
store_name = self.get_credential_store(registry)
|
286
286
|
if store_name is not None:
|
@@ -387,8 +387,8 @@ def decode_auth(auth: Union[str, bytes]) -> Tuple[str, str]:
|
|
387
387
|
def parse_auth(
|
388
388
|
entries: Dict, raise_on_error: bool = False
|
389
389
|
) -> Dict[str, Dict[str, Any]]:
|
390
|
-
"""
|
391
|
-
|
390
|
+
"""Parse authentication entries.
|
391
|
+
|
392
392
|
Arguments:
|
393
393
|
entries: Dict of authentication entries.
|
394
394
|
raise_on_error: If set to true, an invalid format will raise
|
@@ -396,7 +396,6 @@ def parse_auth(
|
|
396
396
|
Returns:
|
397
397
|
Authentication registry.
|
398
398
|
"""
|
399
|
-
|
400
399
|
return AuthConfig.parse_auth(entries, raise_on_error)
|
401
400
|
|
402
401
|
|
wandb/env.py
CHANGED
@@ -74,7 +74,6 @@ DATA_DIR = "WANDB_DATA_DIR"
|
|
74
74
|
CACHE_DIR = "WANDB_CACHE_DIR"
|
75
75
|
DISABLE_SSL = "WANDB_INSECURE_DISABLE_SSL"
|
76
76
|
SERVICE = "WANDB_SERVICE"
|
77
|
-
REQUIRE_SERVICE = "WANDB_REQUIRE_SERVICE"
|
78
77
|
_DISABLE_SERVICE = "WANDB_DISABLE_SERVICE"
|
79
78
|
SENTRY_DSN = "WANDB_SENTRY_DSN"
|
80
79
|
INIT_TIMEOUT = "WANDB_INIT_TIMEOUT"
|