wandb 0.15.9__py3-none-any.whl → 0.15.11__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- wandb/__init__.py +5 -1
- wandb/apis/public.py +137 -17
- wandb/apis/reports/_panels.py +1 -1
- wandb/apis/reports/blocks.py +1 -0
- wandb/apis/reports/report.py +27 -5
- wandb/cli/cli.py +52 -41
- wandb/docker/__init__.py +17 -0
- wandb/docker/auth.py +1 -1
- wandb/env.py +24 -4
- wandb/filesync/step_checksum.py +3 -3
- wandb/integration/openai/openai.py +3 -0
- wandb/integration/ultralytics/__init__.py +9 -0
- wandb/integration/ultralytics/bbox_utils.py +196 -0
- wandb/integration/ultralytics/callback.py +458 -0
- wandb/integration/ultralytics/classification_utils.py +66 -0
- wandb/integration/ultralytics/mask_utils.py +141 -0
- wandb/integration/ultralytics/pose_utils.py +92 -0
- wandb/integration/xgboost/xgboost.py +3 -3
- wandb/integration/yolov8/__init__.py +0 -7
- wandb/integration/yolov8/yolov8.py +22 -3
- wandb/old/settings.py +7 -0
- wandb/plot/line_series.py +0 -1
- wandb/proto/v3/wandb_internal_pb2.py +353 -300
- wandb/proto/v3/wandb_server_pb2.py +37 -41
- wandb/proto/v3/wandb_settings_pb2.py +2 -2
- wandb/proto/v3/wandb_telemetry_pb2.py +16 -16
- wandb/proto/v4/wandb_internal_pb2.py +272 -260
- wandb/proto/v4/wandb_server_pb2.py +37 -40
- wandb/proto/v4/wandb_settings_pb2.py +2 -2
- wandb/proto/v4/wandb_telemetry_pb2.py +16 -16
- wandb/proto/wandb_internal_codegen.py +7 -31
- wandb/sdk/artifacts/artifact.py +321 -189
- wandb/sdk/artifacts/artifact_cache.py +14 -0
- wandb/sdk/artifacts/artifact_manifest.py +5 -4
- wandb/sdk/artifacts/artifact_manifest_entry.py +37 -9
- wandb/sdk/artifacts/artifact_manifests/artifact_manifest_v1.py +1 -9
- wandb/sdk/artifacts/artifact_saver.py +13 -50
- wandb/sdk/artifacts/artifact_ttl.py +6 -0
- wandb/sdk/artifacts/artifacts_cache.py +119 -93
- wandb/sdk/artifacts/staging.py +25 -0
- wandb/sdk/artifacts/storage_handlers/s3_handler.py +12 -7
- wandb/sdk/artifacts/storage_handlers/wb_local_artifact_handler.py +2 -3
- wandb/sdk/artifacts/storage_policies/__init__.py +4 -0
- wandb/sdk/artifacts/storage_policies/register.py +1 -0
- wandb/sdk/artifacts/storage_policies/wandb_storage_policy.py +4 -3
- wandb/sdk/artifacts/storage_policy.py +4 -2
- wandb/sdk/backend/backend.py +0 -16
- wandb/sdk/data_types/image.py +3 -1
- wandb/sdk/integration_utils/auto_logging.py +38 -13
- wandb/sdk/interface/interface.py +16 -135
- wandb/sdk/interface/interface_shared.py +9 -147
- wandb/sdk/interface/interface_sock.py +0 -26
- wandb/sdk/internal/file_pusher.py +20 -3
- wandb/sdk/internal/file_stream.py +3 -1
- wandb/sdk/internal/handler.py +53 -70
- wandb/sdk/internal/internal_api.py +220 -130
- wandb/sdk/internal/job_builder.py +41 -37
- wandb/sdk/internal/sender.py +7 -25
- wandb/sdk/internal/system/assets/disk.py +144 -11
- wandb/sdk/internal/system/system_info.py +6 -2
- wandb/sdk/launch/__init__.py +5 -0
- wandb/sdk/launch/{launch.py → _launch.py} +53 -54
- wandb/sdk/launch/{launch_add.py → _launch_add.py} +34 -31
- wandb/sdk/launch/_project_spec.py +13 -2
- wandb/sdk/launch/agent/agent.py +103 -59
- wandb/sdk/launch/agent/run_queue_item_file_saver.py +6 -4
- wandb/sdk/launch/builder/build.py +19 -1
- wandb/sdk/launch/builder/docker_builder.py +5 -1
- wandb/sdk/launch/builder/kaniko_builder.py +5 -1
- wandb/sdk/launch/create_job.py +20 -5
- wandb/sdk/launch/loader.py +14 -5
- wandb/sdk/launch/runner/abstract.py +0 -2
- wandb/sdk/launch/runner/kubernetes_monitor.py +329 -0
- wandb/sdk/launch/runner/kubernetes_runner.py +66 -209
- wandb/sdk/launch/runner/local_container.py +5 -2
- wandb/sdk/launch/runner/local_process.py +4 -1
- wandb/sdk/launch/sweeps/scheduler.py +43 -25
- wandb/sdk/launch/sweeps/utils.py +5 -3
- wandb/sdk/launch/utils.py +3 -1
- wandb/sdk/lib/_settings_toposort_generate.py +3 -9
- wandb/sdk/lib/_settings_toposort_generated.py +27 -3
- wandb/sdk/lib/_wburls_generated.py +1 -0
- wandb/sdk/lib/filenames.py +27 -6
- wandb/sdk/lib/filesystem.py +181 -7
- wandb/sdk/lib/fsm.py +5 -3
- wandb/sdk/lib/gql_request.py +3 -0
- wandb/sdk/lib/ipython.py +7 -0
- wandb/sdk/lib/wburls.py +1 -0
- wandb/sdk/service/port_file.py +2 -15
- wandb/sdk/service/server.py +7 -55
- wandb/sdk/service/service.py +56 -26
- wandb/sdk/service/service_base.py +1 -1
- wandb/sdk/service/streams.py +11 -5
- wandb/sdk/verify/verify.py +2 -2
- wandb/sdk/wandb_init.py +8 -2
- wandb/sdk/wandb_manager.py +4 -14
- wandb/sdk/wandb_run.py +143 -53
- wandb/sdk/wandb_settings.py +148 -35
- wandb/testing/relay.py +85 -38
- wandb/util.py +87 -4
- wandb/wandb_torch.py +24 -38
- {wandb-0.15.9.dist-info → wandb-0.15.11.dist-info}/METADATA +48 -23
- {wandb-0.15.9.dist-info → wandb-0.15.11.dist-info}/RECORD +107 -103
- {wandb-0.15.9.dist-info → wandb-0.15.11.dist-info}/WHEEL +1 -1
- wandb/proto/v3/wandb_server_pb2_grpc.py +0 -1422
- wandb/proto/v4/wandb_server_pb2_grpc.py +0 -1422
- wandb/proto/wandb_server_pb2_grpc.py +0 -8
- wandb/sdk/artifacts/storage_policies/s3_bucket_policy.py +0 -61
- wandb/sdk/interface/interface_grpc.py +0 -460
- wandb/sdk/service/server_grpc.py +0 -444
- wandb/sdk/service/service_grpc.py +0 -73
- {wandb-0.15.9.dist-info → wandb-0.15.11.dist-info}/LICENSE +0 -0
- {wandb-0.15.9.dist-info → wandb-0.15.11.dist-info}/entry_points.txt +0 -0
- {wandb-0.15.9.dist-info → wandb-0.15.11.dist-info}/top_level.txt +0 -0
wandb/sdk/wandb_settings.py
CHANGED
@@ -32,7 +32,7 @@ from typing import (
|
|
32
32
|
Union,
|
33
33
|
no_type_check,
|
34
34
|
)
|
35
|
-
from urllib.parse import quote, urlencode, urlparse, urlsplit
|
35
|
+
from urllib.parse import quote, unquote, urlencode, urlparse, urlsplit
|
36
36
|
|
37
37
|
from google.protobuf.wrappers_pb2 import BoolValue, DoubleValue, Int32Value, StringValue
|
38
38
|
|
@@ -170,13 +170,18 @@ def _get_program() -> Optional[str]:
|
|
170
170
|
return None
|
171
171
|
|
172
172
|
|
173
|
-
def
|
174
|
-
program: str, _logger: Optional[_EarlyLogger] = None
|
173
|
+
def _get_program_relpath(
|
174
|
+
program: str, root: Optional[str] = None, _logger: Optional[_EarlyLogger] = None
|
175
175
|
) -> Optional[str]:
|
176
|
-
|
177
|
-
|
176
|
+
if not program:
|
177
|
+
if _logger is not None:
|
178
|
+
_logger.warning("Empty program passed to get_program_relpath")
|
179
|
+
return None
|
180
|
+
|
181
|
+
root = root or os.getcwd()
|
178
182
|
if not root:
|
179
|
-
|
183
|
+
return None
|
184
|
+
|
180
185
|
full_path_to_program = os.path.join(
|
181
186
|
root, os.path.relpath(os.getcwd(), root), program
|
182
187
|
)
|
@@ -304,12 +309,27 @@ class SettingsData:
|
|
304
309
|
_disable_setproctitle: bool # Do not use setproctitle on internal process
|
305
310
|
_disable_stats: bool # Do not collect system metrics
|
306
311
|
_disable_viewer: bool # Prevent early viewer query
|
312
|
+
_disable_machine_info: bool # Disable automatic machine info collection
|
307
313
|
_except_exit: bool
|
308
314
|
_executable: str
|
309
315
|
_extra_http_headers: Mapping[str, str]
|
310
|
-
|
316
|
+
# file stream retry client configuration
|
317
|
+
_file_stream_retry_max: int # max number of retries
|
318
|
+
_file_stream_retry_wait_min_seconds: int # min wait time between retries
|
319
|
+
_file_stream_retry_wait_max_seconds: int # max wait time between retries
|
320
|
+
_file_stream_timeout_seconds: int # timeout for individual HTTP requests
|
321
|
+
# file uploader retry client configuration
|
322
|
+
_file_uploader_retry_max: int
|
323
|
+
_file_uploader_retry_wait_min_seconds: int
|
324
|
+
_file_uploader_retry_wait_max_seconds: int
|
325
|
+
_file_uploader_timeout_seconds: int
|
311
326
|
_flow_control_custom: bool
|
312
327
|
_flow_control_disabled: bool
|
328
|
+
# graphql retry client configuration
|
329
|
+
_graphql_retry_max: int
|
330
|
+
_graphql_retry_wait_min_seconds: int
|
331
|
+
_graphql_retry_wait_max_seconds: int
|
332
|
+
_graphql_timeout_seconds: int
|
313
333
|
_internal_check_process: float
|
314
334
|
_internal_queue_timeout: float
|
315
335
|
_ipython: bool
|
@@ -328,6 +348,7 @@ class SettingsData:
|
|
328
348
|
_sync: bool
|
329
349
|
_os: str
|
330
350
|
_platform: str
|
351
|
+
_proxies: Mapping[str, str] # dedicated global proxy servers [scheme -> url]
|
331
352
|
_python: str
|
332
353
|
_runqueue_item_id: str
|
333
354
|
_require_nexus: bool
|
@@ -346,6 +367,7 @@ class SettingsData:
|
|
346
367
|
# - {"metric regex pattern, including endpoint name as prefix": {"label": "label value regex pattern"}}
|
347
368
|
# - ("metric regex pattern 1", "metric regex pattern 2", ...)
|
348
369
|
_stats_open_metrics_filters: Union[Sequence[str], Mapping[str, Mapping[str, str]]]
|
370
|
+
_stats_disk_paths: Sequence[str] # paths to monitor disk usage
|
349
371
|
_tmp_code_dir: str
|
350
372
|
_tracelog: str
|
351
373
|
_unsaved_keys: Sequence[str]
|
@@ -356,6 +378,7 @@ class SettingsData:
|
|
356
378
|
azure_account_url_to_access_key: Dict[str, str]
|
357
379
|
base_url: str # The base url for the wandb api
|
358
380
|
code_dir: str
|
381
|
+
colab_url: str
|
359
382
|
config_paths: Sequence[str]
|
360
383
|
console: str
|
361
384
|
deployment: str
|
@@ -394,7 +417,8 @@ class SettingsData:
|
|
394
417
|
notebook_name: str
|
395
418
|
problem: str
|
396
419
|
program: str
|
397
|
-
|
420
|
+
program_abspath: str
|
421
|
+
program_relpath: str
|
398
422
|
project: str
|
399
423
|
project_url: str
|
400
424
|
quiet: bool
|
@@ -587,29 +611,65 @@ class Settings(SettingsData):
|
|
587
611
|
Note that key names must be the same as the class attribute names.
|
588
612
|
"""
|
589
613
|
props: Dict[str, Dict[str, Any]] = dict(
|
614
|
+
_async_upload_concurrency_limit={
|
615
|
+
"preprocessor": int,
|
616
|
+
"validator": self._validate__async_upload_concurrency_limit,
|
617
|
+
},
|
590
618
|
_aws_lambda={
|
591
619
|
"hook": lambda _: is_aws_lambda(),
|
592
620
|
"auto_hook": True,
|
593
621
|
},
|
594
|
-
|
595
|
-
"
|
596
|
-
"
|
622
|
+
_colab={
|
623
|
+
"hook": lambda _: "google.colab" in sys.modules,
|
624
|
+
"auto_hook": True,
|
625
|
+
},
|
626
|
+
_disable_machine_info={
|
627
|
+
"value": False,
|
628
|
+
"preprocessor": _str_as_bool,
|
629
|
+
},
|
630
|
+
_disable_meta={
|
631
|
+
"value": False,
|
632
|
+
"preprocessor": _str_as_bool,
|
633
|
+
"hook": lambda x: self._disable_machine_info or x,
|
597
634
|
},
|
598
|
-
_disable_meta={"preprocessor": _str_as_bool},
|
599
635
|
_disable_service={
|
600
636
|
"value": False,
|
601
637
|
"preprocessor": _str_as_bool,
|
602
638
|
"is_policy": True,
|
603
639
|
},
|
604
640
|
_disable_setproctitle={"value": False, "preprocessor": _str_as_bool},
|
605
|
-
_disable_stats={
|
641
|
+
_disable_stats={
|
642
|
+
"value": False,
|
643
|
+
"preprocessor": _str_as_bool,
|
644
|
+
"hook": lambda x: self._disable_machine_info or x,
|
645
|
+
},
|
606
646
|
_disable_viewer={"preprocessor": _str_as_bool},
|
607
647
|
_extra_http_headers={"preprocessor": _str_as_json},
|
608
|
-
|
609
|
-
|
610
|
-
|
648
|
+
# Retry filestream requests for 2 hours before dropping chunk (how do we recover?)
|
649
|
+
# retry_count = seconds_in_2_hours / max_retry_time + num_retries_until_max_60_sec
|
650
|
+
# = 7200 / 60 + ceil(log2(60/2))
|
651
|
+
# = 120 + 5
|
652
|
+
_file_stream_retry_max={"value": 125, "preprocessor": int},
|
653
|
+
_file_stream_retry_wait_min_seconds={"value": 2, "preprocessor": int},
|
654
|
+
_file_stream_retry_wait_max_seconds={"value": 60, "preprocessor": int},
|
655
|
+
# A 3 minute timeout for all filestream post requests
|
656
|
+
_file_stream_timeout_seconds={"value": 180, "preprocessor": int},
|
657
|
+
_file_uploader_retry_max={"value": 10, "preprocessor": int},
|
658
|
+
_file_uploader_retry_wait_min_seconds={"value": 2, "preprocessor": int},
|
659
|
+
_file_uploader_retry_wait_max_seconds={"value": 60, "preprocessor": int},
|
660
|
+
_file_uploader_timeout_seconds={"value": 0, "preprocessor": int},
|
661
|
+
_flow_control_disabled={
|
662
|
+
"hook": lambda _: self._network_buffer == 0,
|
663
|
+
"auto_hook": True,
|
664
|
+
},
|
665
|
+
_flow_control_custom={
|
666
|
+
"hook": lambda _: bool(self._network_buffer),
|
611
667
|
"auto_hook": True,
|
612
668
|
},
|
669
|
+
_graphql_retry_max={"value": 10, "preprocessor": int},
|
670
|
+
_graphql_retry_wait_min_seconds={"value": 2, "preprocessor": int},
|
671
|
+
_graphql_retry_wait_max_seconds={"value": 60, "preprocessor": int},
|
672
|
+
_graphql_timeout_seconds={"value": 30.0, "preprocessor": int},
|
613
673
|
_internal_check_process={"value": 8, "preprocessor": float},
|
614
674
|
_internal_queue_timeout={"value": 2, "preprocessor": float},
|
615
675
|
_ipython={
|
@@ -622,6 +682,7 @@ class Settings(SettingsData):
|
|
622
682
|
},
|
623
683
|
_kaggle={"hook": lambda _: util._is_likely_kaggle(), "auto_hook": True},
|
624
684
|
_log_level={"value": logging.DEBUG},
|
685
|
+
_network_buffer={"preprocessor": int},
|
625
686
|
_noop={"hook": lambda _: self.mode == "disabled", "auto_hook": True},
|
626
687
|
_notebook={
|
627
688
|
"hook": lambda _: self._ipython
|
@@ -638,20 +699,10 @@ class Settings(SettingsData):
|
|
638
699
|
),
|
639
700
|
"auto_hook": True,
|
640
701
|
},
|
641
|
-
_file_stream_timeout_seconds={
|
642
|
-
"value": 60,
|
643
|
-
"preprocessor": float,
|
644
|
-
},
|
645
|
-
_flow_control_disabled={
|
646
|
-
"hook": lambda _: self._network_buffer == 0,
|
647
|
-
"auto_hook": True,
|
648
|
-
},
|
649
|
-
_flow_control_custom={
|
650
|
-
"hook": lambda _: bool(self._network_buffer),
|
651
|
-
"auto_hook": True,
|
652
|
-
},
|
653
|
-
_sync={"value": False},
|
654
702
|
_platform={"value": util.get_platform_name()},
|
703
|
+
_proxies={
|
704
|
+
"preprocessor": _str_as_json,
|
705
|
+
},
|
655
706
|
_require_nexus={"value": False, "preprocessor": _str_as_bool},
|
656
707
|
_save_requirements={"value": True, "preprocessor": _str_as_bool},
|
657
708
|
_service_wait={
|
@@ -682,6 +733,11 @@ class Settings(SettingsData):
|
|
682
733
|
"value": (".*",),
|
683
734
|
"preprocessor": _str_as_json,
|
684
735
|
},
|
736
|
+
_stats_disk_paths={
|
737
|
+
"value": ("/",),
|
738
|
+
"preprocessor": _str_as_json,
|
739
|
+
},
|
740
|
+
_sync={"value": False},
|
685
741
|
_tmp_code_dir={
|
686
742
|
"value": "code",
|
687
743
|
"hook": lambda x: self._path_convert(self.tmp_dir, x),
|
@@ -697,6 +753,10 @@ class Settings(SettingsData):
|
|
697
753
|
"preprocessor": lambda x: str(x).strip().rstrip("/"),
|
698
754
|
"validator": self._validate_base_url,
|
699
755
|
},
|
756
|
+
colab_url={
|
757
|
+
"hook": lambda _: self._get_colab_url(),
|
758
|
+
"auto_hook": True,
|
759
|
+
},
|
700
760
|
config_paths={"preprocessor": _str_as_tuple},
|
701
761
|
console={
|
702
762
|
"value": "auto",
|
@@ -708,10 +768,22 @@ class Settings(SettingsData):
|
|
708
768
|
"hook": lambda _: "local" if self.is_local else "cloud",
|
709
769
|
"auto_hook": True,
|
710
770
|
},
|
711
|
-
disable_code={
|
771
|
+
disable_code={
|
772
|
+
"value": False,
|
773
|
+
"preprocessor": _str_as_bool,
|
774
|
+
"hook": lambda x: self._disable_machine_info or x,
|
775
|
+
},
|
712
776
|
disable_hints={"preprocessor": _str_as_bool},
|
713
|
-
disable_git={
|
714
|
-
|
777
|
+
disable_git={
|
778
|
+
"value": False,
|
779
|
+
"preprocessor": _str_as_bool,
|
780
|
+
"hook": lambda x: self._disable_machine_info or x,
|
781
|
+
},
|
782
|
+
disable_job_creation={
|
783
|
+
"value": False,
|
784
|
+
"preprocessor": _str_as_bool,
|
785
|
+
"hook": lambda x: self._disable_machine_info or x,
|
786
|
+
},
|
715
787
|
disabled={"value": False, "preprocessor": _str_as_bool},
|
716
788
|
files_dir={
|
717
789
|
"value": "files",
|
@@ -726,7 +798,7 @@ class Settings(SettingsData):
|
|
726
798
|
"value": tuple(),
|
727
799
|
"preprocessor": lambda x: tuple(x) if not isinstance(x, tuple) else x,
|
728
800
|
},
|
729
|
-
init_timeout={"value":
|
801
|
+
init_timeout={"value": 90, "preprocessor": lambda x: float(x)},
|
730
802
|
is_local={
|
731
803
|
"hook": (
|
732
804
|
lambda _: self.base_url != "https://api.wandb.ai"
|
@@ -764,6 +836,9 @@ class Settings(SettingsData):
|
|
764
836
|
login_timeout={"preprocessor": lambda x: float(x)},
|
765
837
|
mode={"value": "online", "validator": self._validate_mode},
|
766
838
|
problem={"value": "fatal", "validator": self._validate_problem},
|
839
|
+
program={
|
840
|
+
"hook": lambda x: self._get_program(x),
|
841
|
+
},
|
767
842
|
project={"validator": self._validate_project},
|
768
843
|
project_url={"hook": lambda _: self._project_url(), "auto_hook": True},
|
769
844
|
quiet={"preprocessor": _str_as_bool},
|
@@ -1134,6 +1209,32 @@ class Settings(SettingsData):
|
|
1134
1209
|
console = "redirect"
|
1135
1210
|
return console
|
1136
1211
|
|
1212
|
+
def _get_colab_url(self) -> Optional[str]:
|
1213
|
+
if not self._colab:
|
1214
|
+
return None
|
1215
|
+
if self._jupyter_path and self._jupyter_path.startswith("fileId="):
|
1216
|
+
unescaped = unquote(self._jupyter_path)
|
1217
|
+
return "https://colab.research.google.com/notebook#" + unescaped
|
1218
|
+
return None
|
1219
|
+
|
1220
|
+
def _get_program(self, program: Optional[str]) -> Optional[str]:
|
1221
|
+
if program is not None and program != "<python with no main file>":
|
1222
|
+
return program
|
1223
|
+
|
1224
|
+
if not self._jupyter:
|
1225
|
+
return program
|
1226
|
+
|
1227
|
+
if self.notebook_name:
|
1228
|
+
return self.notebook_name
|
1229
|
+
|
1230
|
+
if not self._jupyter_path:
|
1231
|
+
return program
|
1232
|
+
|
1233
|
+
if self._jupyter_path.startswith("fileId="):
|
1234
|
+
return self._jupyter_name
|
1235
|
+
else:
|
1236
|
+
return self._jupyter_path
|
1237
|
+
|
1137
1238
|
def _get_url_query_string(self) -> str:
|
1138
1239
|
# TODO(settings) use `wandb_setting` (if self.anonymous != "true":)
|
1139
1240
|
if Api().settings().get("anonymous") != "true":
|
@@ -1545,6 +1646,9 @@ class Settings(SettingsData):
|
|
1545
1646
|
"WANDB_NOTES": "run_notes",
|
1546
1647
|
"WANDB_TAGS": "run_tags",
|
1547
1648
|
"WANDB_JOB_TYPE": "run_job_type",
|
1649
|
+
"WANDB_HTTP_TIMEOUT": "_graphql_timeout_seconds",
|
1650
|
+
"WANDB_FILE_PUSHER_TIMEOUT": "_file_uploader_timeout_seconds",
|
1651
|
+
"WANDB_USER_EMAIL": "email",
|
1548
1652
|
}
|
1549
1653
|
env = dict()
|
1550
1654
|
for setting, value in environ.items():
|
@@ -1665,10 +1769,18 @@ class Settings(SettingsData):
|
|
1665
1769
|
settings: Dict[str, Union[bool, str, None]] = dict()
|
1666
1770
|
program = self.program or _get_program()
|
1667
1771
|
if program is not None:
|
1668
|
-
|
1669
|
-
|
1772
|
+
repo = GitRepo()
|
1773
|
+
root = repo.root or os.getcwd()
|
1774
|
+
|
1775
|
+
program_relpath = self.program_relpath or _get_program_relpath(
|
1776
|
+
program, repo.root, _logger=_logger
|
1670
1777
|
)
|
1671
1778
|
settings["program_relpath"] = program_relpath
|
1779
|
+
program_abspath = os.path.abspath(
|
1780
|
+
os.path.join(root, os.path.relpath(os.getcwd(), root), program)
|
1781
|
+
)
|
1782
|
+
if os.path.exists(program_abspath):
|
1783
|
+
settings["program_abspath"] = program_abspath
|
1672
1784
|
else:
|
1673
1785
|
program = "<python with no main file>"
|
1674
1786
|
|
@@ -1731,6 +1843,7 @@ class Settings(SettingsData):
|
|
1731
1843
|
job_type="run_job_type",
|
1732
1844
|
notes="run_notes",
|
1733
1845
|
dir="root_dir",
|
1846
|
+
sweep_id="sweep_id",
|
1734
1847
|
)
|
1735
1848
|
init_settings = {
|
1736
1849
|
param_map.get(k, k): v for k, v in init_settings.items() if v is not None
|
wandb/testing/relay.py
CHANGED
@@ -74,6 +74,18 @@ class DeliberateHTTPError(Exception):
|
|
74
74
|
return f"DeliberateHTTPError({self.message!r}, {self.status_code!r})"
|
75
75
|
|
76
76
|
|
77
|
+
@dataclasses.dataclass
|
78
|
+
class RunAttrs:
|
79
|
+
"""Simple data class for run attributes."""
|
80
|
+
|
81
|
+
name: str
|
82
|
+
display_name: str
|
83
|
+
description: str
|
84
|
+
sweep_name: str
|
85
|
+
project: Dict[str, Any]
|
86
|
+
config: Dict[str, Any]
|
87
|
+
|
88
|
+
|
77
89
|
class Context:
|
78
90
|
"""A container used to store the snooped state/data of a test.
|
79
91
|
|
@@ -223,6 +235,20 @@ class Context:
|
|
223
235
|
run_stats = self.events[mask_run]
|
224
236
|
return run_stats
|
225
237
|
|
238
|
+
def get_run_attrs(self, run_id: str) -> Optional[RunAttrs]:
|
239
|
+
run_entry = self._entries.get(run_id)
|
240
|
+
if not run_entry:
|
241
|
+
return None
|
242
|
+
|
243
|
+
return RunAttrs(
|
244
|
+
name=run_entry["name"],
|
245
|
+
display_name=run_entry["displayName"],
|
246
|
+
description=run_entry["description"],
|
247
|
+
sweep_name=run_entry["sweepName"],
|
248
|
+
project=run_entry["project"],
|
249
|
+
config=run_entry["config"],
|
250
|
+
)
|
251
|
+
|
226
252
|
# todo: add getter (by run_id) utilities for other properties
|
227
253
|
|
228
254
|
|
@@ -317,8 +343,8 @@ class QueryResolver:
|
|
317
343
|
query = "CreateRunFiles" in request_data.get("query", "")
|
318
344
|
if query:
|
319
345
|
run_name = request_data["variables"]["run"]
|
320
|
-
files = (
|
321
|
-
|
346
|
+
files = ((response_data.get("data") or {}).get("createRunFiles") or {}).get(
|
347
|
+
"files", {}
|
322
348
|
)
|
323
349
|
post_processed_data = {
|
324
350
|
"name": run_name,
|
@@ -526,6 +552,7 @@ class RelayServer:
|
|
526
552
|
base_url: str,
|
527
553
|
inject: Optional[List[InjectedResponse]] = None,
|
528
554
|
control: Optional[RelayControlProtocol] = None,
|
555
|
+
verbose: bool = False,
|
529
556
|
) -> None:
|
530
557
|
# todo for the future:
|
531
558
|
# - consider switching from Flask to Quart
|
@@ -581,6 +608,7 @@ class RelayServer:
|
|
581
608
|
|
582
609
|
# useful when debugging:
|
583
610
|
# self.after_request_fn = self.app.after_request(self.after_request_fn)
|
611
|
+
self.verbose = verbose
|
584
612
|
|
585
613
|
@staticmethod
|
586
614
|
def handle_http_exception(e):
|
@@ -632,11 +660,25 @@ class RelayServer:
|
|
632
660
|
json=request.get_json(),
|
633
661
|
).prepare()
|
634
662
|
|
663
|
+
if self.verbose:
|
664
|
+
print("*****************")
|
665
|
+
print("RELAY REQUEST:")
|
666
|
+
print(prepared_relayed_request.url)
|
667
|
+
print(prepared_relayed_request.method)
|
668
|
+
print(prepared_relayed_request.headers)
|
669
|
+
print(prepared_relayed_request.body)
|
670
|
+
print("*****************")
|
671
|
+
|
635
672
|
for injected_response in self.inject:
|
636
673
|
# where are we in the application pattern?
|
637
674
|
should_apply = injected_response.application_pattern.should_apply()
|
638
675
|
# check if an injected response matches the request
|
639
676
|
if injected_response == prepared_relayed_request:
|
677
|
+
if self.verbose:
|
678
|
+
print("*****************")
|
679
|
+
print("INJECTING RESPONSE:")
|
680
|
+
print(injected_response.to_dict())
|
681
|
+
print("*****************")
|
640
682
|
# rotate the injection pattern
|
641
683
|
injected_response.application_pattern.next()
|
642
684
|
if should_apply:
|
@@ -693,19 +735,21 @@ class RelayServer:
|
|
693
735
|
request = flask.request
|
694
736
|
with Timer() as timer:
|
695
737
|
relayed_response = self.relay(request)
|
696
|
-
|
697
|
-
|
698
|
-
|
699
|
-
|
700
|
-
|
701
|
-
|
738
|
+
if self.verbose:
|
739
|
+
print("*****************")
|
740
|
+
print("GRAPHQL REQUEST:")
|
741
|
+
print(request.get_json())
|
742
|
+
print("GRAPHQL RESPONSE:")
|
743
|
+
print(relayed_response.status_code, relayed_response.json())
|
744
|
+
print("*****************")
|
702
745
|
# snoop work to extract the context
|
703
746
|
self.snoop_context(request, relayed_response, timer.elapsed)
|
704
|
-
|
705
|
-
|
706
|
-
|
707
|
-
|
708
|
-
|
747
|
+
if self.verbose:
|
748
|
+
print("*****************")
|
749
|
+
print("SNOOPED CONTEXT:")
|
750
|
+
print(self.context.entries)
|
751
|
+
print(len(self.context.raw_data))
|
752
|
+
print("*****************")
|
709
753
|
|
710
754
|
return relayed_response.json()
|
711
755
|
|
@@ -713,16 +757,17 @@ class RelayServer:
|
|
713
757
|
request = flask.request
|
714
758
|
with Timer() as timer:
|
715
759
|
relayed_response = self.relay(request)
|
716
|
-
|
717
|
-
|
718
|
-
|
719
|
-
|
720
|
-
|
721
|
-
|
722
|
-
|
723
|
-
|
724
|
-
|
725
|
-
|
760
|
+
if self.verbose:
|
761
|
+
print("*****************")
|
762
|
+
print("FILE STREAM REQUEST:")
|
763
|
+
print("********PATH*********")
|
764
|
+
print(path)
|
765
|
+
print("********ENDPATH*********")
|
766
|
+
print(request.get_json())
|
767
|
+
print("FILE STREAM RESPONSE:")
|
768
|
+
print(relayed_response)
|
769
|
+
print(relayed_response.status_code, relayed_response.json())
|
770
|
+
print("*****************")
|
726
771
|
|
727
772
|
self.snoop_context(request, relayed_response, timer.elapsed, path=path)
|
728
773
|
|
@@ -732,12 +777,13 @@ class RelayServer:
|
|
732
777
|
request = flask.request
|
733
778
|
with Timer() as timer:
|
734
779
|
relayed_response = self.relay(request)
|
735
|
-
|
736
|
-
|
737
|
-
|
738
|
-
|
739
|
-
|
740
|
-
|
780
|
+
if self.verbose:
|
781
|
+
print("*****************")
|
782
|
+
print("STORAGE REQUEST:")
|
783
|
+
print(request.get_json())
|
784
|
+
print("STORAGE RESPONSE:")
|
785
|
+
print(relayed_response.status_code, relayed_response.json())
|
786
|
+
print("*****************")
|
741
787
|
|
742
788
|
self.snoop_context(request, relayed_response, timer.elapsed)
|
743
789
|
|
@@ -747,15 +793,16 @@ class RelayServer:
|
|
747
793
|
request = flask.request
|
748
794
|
with Timer() as timer:
|
749
795
|
relayed_response = self.relay(request)
|
750
|
-
|
751
|
-
|
752
|
-
|
753
|
-
|
754
|
-
|
755
|
-
|
756
|
-
|
757
|
-
|
758
|
-
|
796
|
+
if self.verbose:
|
797
|
+
print("*****************")
|
798
|
+
print("STORAGE FILE REQUEST:")
|
799
|
+
print("********PATH*********")
|
800
|
+
print(path)
|
801
|
+
print("********ENDPATH*********")
|
802
|
+
print(request.get_json())
|
803
|
+
print("STORAGE FILE RESPONSE:")
|
804
|
+
print(relayed_response.json())
|
805
|
+
print("*****************")
|
759
806
|
|
760
807
|
self.snoop_context(request, relayed_response, timer.elapsed, path=path)
|
761
808
|
|