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.
Files changed (114) hide show
  1. wandb/__init__.py +5 -1
  2. wandb/apis/public.py +137 -17
  3. wandb/apis/reports/_panels.py +1 -1
  4. wandb/apis/reports/blocks.py +1 -0
  5. wandb/apis/reports/report.py +27 -5
  6. wandb/cli/cli.py +52 -41
  7. wandb/docker/__init__.py +17 -0
  8. wandb/docker/auth.py +1 -1
  9. wandb/env.py +24 -4
  10. wandb/filesync/step_checksum.py +3 -3
  11. wandb/integration/openai/openai.py +3 -0
  12. wandb/integration/ultralytics/__init__.py +9 -0
  13. wandb/integration/ultralytics/bbox_utils.py +196 -0
  14. wandb/integration/ultralytics/callback.py +458 -0
  15. wandb/integration/ultralytics/classification_utils.py +66 -0
  16. wandb/integration/ultralytics/mask_utils.py +141 -0
  17. wandb/integration/ultralytics/pose_utils.py +92 -0
  18. wandb/integration/xgboost/xgboost.py +3 -3
  19. wandb/integration/yolov8/__init__.py +0 -7
  20. wandb/integration/yolov8/yolov8.py +22 -3
  21. wandb/old/settings.py +7 -0
  22. wandb/plot/line_series.py +0 -1
  23. wandb/proto/v3/wandb_internal_pb2.py +353 -300
  24. wandb/proto/v3/wandb_server_pb2.py +37 -41
  25. wandb/proto/v3/wandb_settings_pb2.py +2 -2
  26. wandb/proto/v3/wandb_telemetry_pb2.py +16 -16
  27. wandb/proto/v4/wandb_internal_pb2.py +272 -260
  28. wandb/proto/v4/wandb_server_pb2.py +37 -40
  29. wandb/proto/v4/wandb_settings_pb2.py +2 -2
  30. wandb/proto/v4/wandb_telemetry_pb2.py +16 -16
  31. wandb/proto/wandb_internal_codegen.py +7 -31
  32. wandb/sdk/artifacts/artifact.py +321 -189
  33. wandb/sdk/artifacts/artifact_cache.py +14 -0
  34. wandb/sdk/artifacts/artifact_manifest.py +5 -4
  35. wandb/sdk/artifacts/artifact_manifest_entry.py +37 -9
  36. wandb/sdk/artifacts/artifact_manifests/artifact_manifest_v1.py +1 -9
  37. wandb/sdk/artifacts/artifact_saver.py +13 -50
  38. wandb/sdk/artifacts/artifact_ttl.py +6 -0
  39. wandb/sdk/artifacts/artifacts_cache.py +119 -93
  40. wandb/sdk/artifacts/staging.py +25 -0
  41. wandb/sdk/artifacts/storage_handlers/s3_handler.py +12 -7
  42. wandb/sdk/artifacts/storage_handlers/wb_local_artifact_handler.py +2 -3
  43. wandb/sdk/artifacts/storage_policies/__init__.py +4 -0
  44. wandb/sdk/artifacts/storage_policies/register.py +1 -0
  45. wandb/sdk/artifacts/storage_policies/wandb_storage_policy.py +4 -3
  46. wandb/sdk/artifacts/storage_policy.py +4 -2
  47. wandb/sdk/backend/backend.py +0 -16
  48. wandb/sdk/data_types/image.py +3 -1
  49. wandb/sdk/integration_utils/auto_logging.py +38 -13
  50. wandb/sdk/interface/interface.py +16 -135
  51. wandb/sdk/interface/interface_shared.py +9 -147
  52. wandb/sdk/interface/interface_sock.py +0 -26
  53. wandb/sdk/internal/file_pusher.py +20 -3
  54. wandb/sdk/internal/file_stream.py +3 -1
  55. wandb/sdk/internal/handler.py +53 -70
  56. wandb/sdk/internal/internal_api.py +220 -130
  57. wandb/sdk/internal/job_builder.py +41 -37
  58. wandb/sdk/internal/sender.py +7 -25
  59. wandb/sdk/internal/system/assets/disk.py +144 -11
  60. wandb/sdk/internal/system/system_info.py +6 -2
  61. wandb/sdk/launch/__init__.py +5 -0
  62. wandb/sdk/launch/{launch.py → _launch.py} +53 -54
  63. wandb/sdk/launch/{launch_add.py → _launch_add.py} +34 -31
  64. wandb/sdk/launch/_project_spec.py +13 -2
  65. wandb/sdk/launch/agent/agent.py +103 -59
  66. wandb/sdk/launch/agent/run_queue_item_file_saver.py +6 -4
  67. wandb/sdk/launch/builder/build.py +19 -1
  68. wandb/sdk/launch/builder/docker_builder.py +5 -1
  69. wandb/sdk/launch/builder/kaniko_builder.py +5 -1
  70. wandb/sdk/launch/create_job.py +20 -5
  71. wandb/sdk/launch/loader.py +14 -5
  72. wandb/sdk/launch/runner/abstract.py +0 -2
  73. wandb/sdk/launch/runner/kubernetes_monitor.py +329 -0
  74. wandb/sdk/launch/runner/kubernetes_runner.py +66 -209
  75. wandb/sdk/launch/runner/local_container.py +5 -2
  76. wandb/sdk/launch/runner/local_process.py +4 -1
  77. wandb/sdk/launch/sweeps/scheduler.py +43 -25
  78. wandb/sdk/launch/sweeps/utils.py +5 -3
  79. wandb/sdk/launch/utils.py +3 -1
  80. wandb/sdk/lib/_settings_toposort_generate.py +3 -9
  81. wandb/sdk/lib/_settings_toposort_generated.py +27 -3
  82. wandb/sdk/lib/_wburls_generated.py +1 -0
  83. wandb/sdk/lib/filenames.py +27 -6
  84. wandb/sdk/lib/filesystem.py +181 -7
  85. wandb/sdk/lib/fsm.py +5 -3
  86. wandb/sdk/lib/gql_request.py +3 -0
  87. wandb/sdk/lib/ipython.py +7 -0
  88. wandb/sdk/lib/wburls.py +1 -0
  89. wandb/sdk/service/port_file.py +2 -15
  90. wandb/sdk/service/server.py +7 -55
  91. wandb/sdk/service/service.py +56 -26
  92. wandb/sdk/service/service_base.py +1 -1
  93. wandb/sdk/service/streams.py +11 -5
  94. wandb/sdk/verify/verify.py +2 -2
  95. wandb/sdk/wandb_init.py +8 -2
  96. wandb/sdk/wandb_manager.py +4 -14
  97. wandb/sdk/wandb_run.py +143 -53
  98. wandb/sdk/wandb_settings.py +148 -35
  99. wandb/testing/relay.py +85 -38
  100. wandb/util.py +87 -4
  101. wandb/wandb_torch.py +24 -38
  102. {wandb-0.15.9.dist-info → wandb-0.15.11.dist-info}/METADATA +48 -23
  103. {wandb-0.15.9.dist-info → wandb-0.15.11.dist-info}/RECORD +107 -103
  104. {wandb-0.15.9.dist-info → wandb-0.15.11.dist-info}/WHEEL +1 -1
  105. wandb/proto/v3/wandb_server_pb2_grpc.py +0 -1422
  106. wandb/proto/v4/wandb_server_pb2_grpc.py +0 -1422
  107. wandb/proto/wandb_server_pb2_grpc.py +0 -8
  108. wandb/sdk/artifacts/storage_policies/s3_bucket_policy.py +0 -61
  109. wandb/sdk/interface/interface_grpc.py +0 -460
  110. wandb/sdk/service/server_grpc.py +0 -444
  111. wandb/sdk/service/service_grpc.py +0 -73
  112. {wandb-0.15.9.dist-info → wandb-0.15.11.dist-info}/LICENSE +0 -0
  113. {wandb-0.15.9.dist-info → wandb-0.15.11.dist-info}/entry_points.txt +0 -0
  114. {wandb-0.15.9.dist-info → wandb-0.15.11.dist-info}/top_level.txt +0 -0
wandb/sdk/wandb_run.py CHANGED
@@ -59,7 +59,7 @@ from wandb.util import (
59
59
  _is_artifact_object,
60
60
  _is_artifact_string,
61
61
  _is_artifact_version_weave_dict,
62
- _is_py_path,
62
+ _is_py_or_dockerfile,
63
63
  _resolve_aliases,
64
64
  add_import_hook,
65
65
  parse_artifact_string,
@@ -99,11 +99,11 @@ if TYPE_CHECKING:
99
99
 
100
100
  import wandb.apis.public
101
101
  import wandb.sdk.backend.backend
102
- import wandb.sdk.interface.interface_grpc
103
102
  import wandb.sdk.interface.interface_queue
104
103
  from wandb.proto.wandb_internal_pb2 import (
105
104
  CheckVersionResponse,
106
105
  GetSummaryResponse,
106
+ InternalMessagesResponse,
107
107
  SampledHistoryResponse,
108
108
  )
109
109
 
@@ -162,6 +162,8 @@ class RunStatusChecker:
162
162
  _stop_status_handle: Optional[MailboxHandle]
163
163
  _network_status_lock: threading.Lock
164
164
  _network_status_handle: Optional[MailboxHandle]
165
+ _internal_messages_lock: threading.Lock
166
+ _internal_messages_handle: Optional[MailboxHandle]
165
167
 
166
168
  def __init__(
167
169
  self,
@@ -191,9 +193,18 @@ class RunStatusChecker:
191
193
  daemon=True,
192
194
  )
193
195
 
196
+ self._internal_messages_lock = threading.Lock()
197
+ self._internal_messages_handle = None
198
+ self._internal_messages_thread = threading.Thread(
199
+ target=self.check_internal_messages,
200
+ name="IntMsgThr",
201
+ daemon=True,
202
+ )
203
+
194
204
  def start(self) -> None:
195
205
  self._stop_thread.start()
196
206
  self._network_status_thread.start()
207
+ self._internal_messages_thread.start()
197
208
 
198
209
  def _loop_check_status(
199
210
  self,
@@ -279,6 +290,20 @@ class RunStatusChecker:
279
290
  process=_process_stop_status,
280
291
  )
281
292
 
293
+ def check_internal_messages(self) -> None:
294
+ def _process_internal_messages(result: Result) -> None:
295
+ internal_messages = result.response.internal_messages_response
296
+ for msg in internal_messages.messages.warning:
297
+ wandb.termwarn(msg)
298
+
299
+ self._loop_check_status(
300
+ lock=self._internal_messages_lock,
301
+ set_handle=lambda x: setattr(self, "_internal_messages_handle", x),
302
+ timeout=1,
303
+ request=self._interface.deliver_internal_messages,
304
+ process=_process_internal_messages,
305
+ )
306
+
282
307
  def stop(self) -> None:
283
308
  self._join_event.set()
284
309
  with self._stop_status_lock:
@@ -287,11 +312,15 @@ class RunStatusChecker:
287
312
  with self._network_status_lock:
288
313
  if self._network_status_handle:
289
314
  self._network_status_handle.abandon()
315
+ with self._internal_messages_lock:
316
+ if self._internal_messages_handle:
317
+ self._internal_messages_handle.abandon()
290
318
 
291
319
  def join(self) -> None:
292
320
  self.stop()
293
321
  self._stop_thread.join()
294
322
  self._network_status_thread.join()
323
+ self._internal_messages_thread.join()
295
324
 
296
325
 
297
326
  class _run_decorator: # noqa: N801
@@ -475,15 +504,13 @@ class Run:
475
504
  _job_type: Optional[str]
476
505
  _name: Optional[str]
477
506
  _notes: Optional[str]
507
+ _sweep_id: Optional[str]
478
508
 
479
509
  _run_obj: Optional[RunRecord]
480
510
  # Use string literal annotation because of type reference loop
481
511
  _backend: Optional["wandb.sdk.backend.backend.Backend"]
482
512
  _internal_run_interface: Optional[
483
- Union[
484
- "wandb.sdk.interface.interface_queue.InterfaceQueue",
485
- "wandb.sdk.interface.interface_grpc.InterfaceGrpc",
486
- ]
513
+ "wandb.sdk.interface.interface_queue.InterfaceQueue"
487
514
  ]
488
515
  _wl: Optional[_WandbSetup]
489
516
 
@@ -507,6 +534,7 @@ class Run:
507
534
  _poll_exit_handle: Optional[MailboxHandle]
508
535
  _poll_exit_response: Optional[PollExitResponse]
509
536
  _server_info_response: Optional[ServerInfoResponse]
537
+ _internal_messages_response: Optional["InternalMessagesResponse"]
510
538
 
511
539
  _stdout_slave_fd: Optional[int]
512
540
  _stderr_slave_fd: Optional[int]
@@ -584,6 +612,7 @@ class Run:
584
612
  self._tags = None
585
613
  self._remote_url = None
586
614
  self._commit = None
615
+ self._sweep_id = None
587
616
 
588
617
  self._hooks = None
589
618
  self._teardown_hooks = []
@@ -609,6 +638,7 @@ class Run:
609
638
  self._final_summary = None
610
639
  self._poll_exit_response = None
611
640
  self._server_info_response = None
641
+ self._internal_messages_response = None
612
642
  self._poll_exit_handle = None
613
643
  self._job_info = None
614
644
 
@@ -752,6 +782,8 @@ class Run:
752
782
  self._notes = settings.run_notes
753
783
  if settings.run_tags is not None:
754
784
  self._tags = settings.run_tags
785
+ if settings.sweep_id is not None:
786
+ self._sweep_id = settings.sweep_id
755
787
 
756
788
  def _make_proto_run(self, run: RunRecord) -> None:
757
789
  """Populate protocol buffer RunData for interface/interface."""
@@ -778,6 +810,8 @@ class Run:
778
810
  run.git.remote_url = self._remote_url
779
811
  if self._commit is not None:
780
812
  run.git.commit = self._commit
813
+ if self._sweep_id is not None:
814
+ run.sweep_id = self._sweep_id
781
815
  # Note: run.config is set in interface/interface:_make_run()
782
816
 
783
817
  def _populate_git_info(self) -> None:
@@ -1050,8 +1084,12 @@ class Run:
1050
1084
  self,
1051
1085
  root: Optional[str] = ".",
1052
1086
  name: Optional[str] = None,
1053
- include_fn: Callable[[str], bool] = _is_py_path,
1054
- exclude_fn: Callable[[str], bool] = filenames.exclude_wandb_fn,
1087
+ include_fn: Union[
1088
+ Callable[[str, str], bool], Callable[[str], bool]
1089
+ ] = _is_py_or_dockerfile,
1090
+ exclude_fn: Union[
1091
+ Callable[[str, str], bool], Callable[[str], bool]
1092
+ ] = filenames.exclude_wandb_fn,
1055
1093
  ) -> Optional[Artifact]:
1056
1094
  """Save the current state of your code to a W&B Artifact.
1057
1095
 
@@ -1062,11 +1100,13 @@ class Run:
1062
1100
  name: (str, optional) The name of our code artifact. By default, we'll name
1063
1101
  the artifact `source-$PROJECT_ID-$ENTRYPOINT_RELPATH`. There may be scenarios where you want
1064
1102
  many runs to share the same artifact. Specifying name allows you to achieve that.
1065
- include_fn: A callable that accepts a file path and
1103
+ include_fn: A callable that accepts a file path and (optionally) root path and
1066
1104
  returns True when it should be included and False otherwise. This
1067
- defaults to: `lambda path: path.endswith(".py")`
1068
- exclude_fn: A callable that accepts a file path and returns `True` when it should be
1069
- excluded and `False` otherwise. This defaults to: `lambda path: False`
1105
+ defaults to: `lambda path, root: path.endswith(".py")`
1106
+ exclude_fn: A callable that accepts a file path and (optionally) root path and
1107
+ returns `True` when it should be excluded and `False` otherwise. This
1108
+ defaults to a function that excludes all files within `<root>/.wandb/`
1109
+ and `<root>/wandb/` directories.
1070
1110
 
1071
1111
  Examples:
1072
1112
  Basic usage
@@ -1077,7 +1117,9 @@ class Run:
1077
1117
  Advanced usage
1078
1118
  ```python
1079
1119
  run.log_code(
1080
- "../", include_fn=lambda path: path.endswith(".py") or path.endswith(".ipynb")
1120
+ "../",
1121
+ include_fn=lambda path: path.endswith(".py") or path.endswith(".ipynb"),
1122
+ exclude_fn=lambda path, root: os.path.relpath(path, root).startswith("cache/"),
1081
1123
  )
1082
1124
  ```
1083
1125
 
@@ -1106,7 +1148,7 @@ class Run:
1106
1148
  files_added = True
1107
1149
  save_name = os.path.relpath(file_path, root)
1108
1150
  art.add_file(file_path, name=save_name)
1109
- # Add any manually staged files such is ipynb notebooks
1151
+ # Add any manually staged files such as ipynb notebooks
1110
1152
  for dirpath, _, files in os.walk(self._settings._tmp_code_dir):
1111
1153
  for fname in files:
1112
1154
  file_path = os.path.join(dirpath, fname)
@@ -1156,7 +1198,7 @@ class Run:
1156
1198
  def entity(self) -> str:
1157
1199
  """The name of the W&B entity associated with the run.
1158
1200
 
1159
- Entity can be a user name or the name of a team or organization.
1201
+ Entity can be a username or the name of a team or organization.
1160
1202
  """
1161
1203
  return self._entity or ""
1162
1204
 
@@ -1437,10 +1479,7 @@ class Run:
1437
1479
 
1438
1480
  def _set_internal_run_interface(
1439
1481
  self,
1440
- interface: Union[
1441
- "wandb.sdk.interface.interface_queue.InterfaceQueue",
1442
- "wandb.sdk.interface.interface_grpc.InterfaceGrpc",
1443
- ],
1482
+ interface: "wandb.sdk.interface.interface_queue.InterfaceQueue",
1444
1483
  ) -> None:
1445
1484
  self._internal_run_interface = interface
1446
1485
 
@@ -1471,7 +1510,8 @@ class Run:
1471
1510
  summary_dict = {}
1472
1511
  for orig in run_obj.summary.update:
1473
1512
  summary_dict[orig.key] = json.loads(orig.value_json)
1474
- self.summary.update(summary_dict)
1513
+ if summary_dict:
1514
+ self.summary.update(summary_dict)
1475
1515
  self._step = self._get_starting_step()
1476
1516
 
1477
1517
  # update settings from run_obj
@@ -2148,7 +2188,7 @@ class Run:
2148
2188
  self._backend.cleanup()
2149
2189
  logger.error("Problem finishing run", exc_info=e)
2150
2190
  wandb.termerror("Problem finishing run")
2151
- traceback.print_exception(*sys.exc_info())
2191
+ traceback.print_exc()
2152
2192
  else:
2153
2193
  self._on_final()
2154
2194
  finally:
@@ -2375,6 +2415,11 @@ class Run:
2375
2415
 
2376
2416
  _ = exit_handle.wait(timeout=-1, on_progress=self._on_progress_exit)
2377
2417
 
2418
+ internal_messages_handle = self._backend.interface.deliver_internal_messages()
2419
+ result = internal_messages_handle.wait(timeout=-1)
2420
+ assert result
2421
+ self._internal_messages_response = result.response.internal_messages_response
2422
+
2378
2423
  # dispatch all our final requests
2379
2424
  poll_exit_handle = self._backend.interface.deliver_poll_exit()
2380
2425
  server_info_handle = self._backend.interface.deliver_request_server_info()
@@ -2421,14 +2466,15 @@ class Run:
2421
2466
 
2422
2467
  def _on_final(self) -> None:
2423
2468
  self._footer(
2424
- self._sampled_history,
2425
- self._final_summary,
2426
- self._poll_exit_response,
2427
- self._server_info_response,
2428
- self._check_version,
2429
- self._job_info,
2430
- self._reporter,
2431
- self._quiet,
2469
+ sampled_history=self._sampled_history,
2470
+ final_summary=self._final_summary,
2471
+ poll_exit_response=self._poll_exit_response,
2472
+ server_info_response=self._server_info_response,
2473
+ check_version_response=self._check_version,
2474
+ internal_messages_response=self._internal_messages_response,
2475
+ job_info=self._job_info,
2476
+ reporter=self._reporter,
2477
+ quiet=self._quiet,
2432
2478
  settings=self._settings,
2433
2479
  printer=self._printer,
2434
2480
  )
@@ -2632,6 +2678,10 @@ class Run:
2632
2678
  entity,
2633
2679
  project,
2634
2680
  )
2681
+ if artifact._ttl_duration_seconds is not None:
2682
+ wandb.termwarn(
2683
+ "Artifact TTL will be disabled for source artifacts that are linked to portfolios."
2684
+ )
2635
2685
  else:
2636
2686
  # TODO: implement offline mode + sync
2637
2687
  raise NotImplementedError
@@ -2958,25 +3008,35 @@ class Run:
2958
3008
 
2959
3009
  # TODO(jhr): annotate this
2960
3010
  def _assert_can_log_artifact(self, artifact) -> None: # type: ignore
2961
- if not self._settings._offline:
2962
- try:
2963
- public_api = self._public_api()
2964
- expected_type = Artifact._expected_type(
2965
- public_api.settings["entity"],
2966
- public_api.settings["project"],
2967
- artifact.name,
2968
- public_api.client,
2969
- )
2970
- except requests.exceptions.RequestException:
2971
- # Just return early if there is a network error. This is
2972
- # ok, as this function is intended to help catch an invalid
2973
- # type early, but not a hard requirement for valid operation.
2974
- return
2975
- if expected_type is not None and artifact.type != expected_type:
2976
- raise ValueError(
2977
- f"Artifact {artifact.name} already exists with type {expected_type}; "
2978
- f"cannot create another with type {artifact.type}"
2979
- )
3011
+ if self._settings._offline:
3012
+ return
3013
+ try:
3014
+ public_api = self._public_api()
3015
+ entity = public_api.settings["entity"]
3016
+ project = public_api.settings["project"]
3017
+ expected_type = Artifact._expected_type(
3018
+ entity, project, artifact.name, public_api.client
3019
+ )
3020
+ except requests.exceptions.RequestException:
3021
+ # Just return early if there is a network error. This is
3022
+ # ok, as this function is intended to help catch an invalid
3023
+ # type early, but not a hard requirement for valid operation.
3024
+ return
3025
+ if expected_type is not None and artifact.type != expected_type:
3026
+ raise ValueError(
3027
+ f"Artifact {artifact.name} already exists with type '{expected_type}'; "
3028
+ f"cannot create another with type '{artifact.type}'"
3029
+ )
3030
+ if entity and artifact._source_entity and entity != artifact._source_entity:
3031
+ raise ValueError(
3032
+ f"Artifact {artifact.name} is owned by entity '{entity}'; it can't be "
3033
+ f"moved to '{artifact._source_entity}'"
3034
+ )
3035
+ if project and artifact._source_project and project != artifact._source_project:
3036
+ raise ValueError(
3037
+ f"Artifact {artifact.name} exists in project '{project}'; it can't be "
3038
+ f"moved to '{artifact._source_project}'"
3039
+ )
2980
3040
 
2981
3041
  def _prepare_artifact(
2982
3042
  self,
@@ -3053,9 +3113,12 @@ class Run:
3053
3113
  exc_val: BaseException,
3054
3114
  exc_tb: TracebackType,
3055
3115
  ) -> bool:
3056
- exit_code = 0 if exc_type is None else 1
3057
- self._finish(exit_code)
3058
- return exc_type is None
3116
+ exception_raised = exc_type is not None
3117
+ if exception_raised:
3118
+ traceback.print_exception(exc_type, exc_val, exc_tb)
3119
+ exit_code = 1 if exception_raised else 0
3120
+ self._finish(exit_code=exit_code)
3121
+ return not exception_raised
3059
3122
 
3060
3123
  @_run_decorator._noop_on_finish()
3061
3124
  @_run_decorator._attach
@@ -3215,7 +3278,8 @@ class Run:
3215
3278
  final_summary: Optional["GetSummaryResponse"] = None,
3216
3279
  poll_exit_response: Optional[PollExitResponse] = None,
3217
3280
  server_info_response: Optional[ServerInfoResponse] = None,
3218
- check_version: Optional["CheckVersionResponse"] = None,
3281
+ check_version_response: Optional["CheckVersionResponse"] = None,
3282
+ internal_messages_response: Optional["InternalMessagesResponse"] = None,
3219
3283
  job_info: Optional["JobInfoResponse"] = None,
3220
3284
  reporter: Optional[Reporter] = None,
3221
3285
  quiet: Optional[bool] = None,
@@ -3240,7 +3304,10 @@ class Run:
3240
3304
  )
3241
3305
  Run._footer_log_dir_info(quiet=quiet, settings=settings, printer=printer)
3242
3306
  Run._footer_version_check_info(
3243
- check_version=check_version, quiet=quiet, settings=settings, printer=printer
3307
+ check_version=check_version_response,
3308
+ quiet=quiet,
3309
+ settings=settings,
3310
+ printer=printer,
3244
3311
  )
3245
3312
  Run._footer_local_warn(
3246
3313
  server_info_response=server_info_response,
@@ -3248,6 +3315,12 @@ class Run:
3248
3315
  settings=settings,
3249
3316
  printer=printer,
3250
3317
  )
3318
+ Run._footer_internal_messages(
3319
+ internal_messages_response=internal_messages_response,
3320
+ quiet=quiet,
3321
+ settings=settings,
3322
+ printer=printer,
3323
+ )
3251
3324
  Run._footer_reporter_warn_err(
3252
3325
  reporter=reporter, quiet=quiet, settings=settings, printer=printer
3253
3326
  )
@@ -3560,6 +3633,23 @@ class Run:
3560
3633
  level="warn",
3561
3634
  )
3562
3635
 
3636
+ @staticmethod
3637
+ def _footer_internal_messages(
3638
+ internal_messages_response: Optional["InternalMessagesResponse"] = None,
3639
+ quiet: Optional[bool] = None,
3640
+ *,
3641
+ settings: "Settings",
3642
+ printer: Union["PrinterTerm", "PrinterJupyter"],
3643
+ ) -> None:
3644
+ if (quiet or settings.quiet) or settings.silent:
3645
+ return
3646
+
3647
+ if not internal_messages_response:
3648
+ return
3649
+
3650
+ for message in internal_messages_response.messages.warning:
3651
+ printer.display(message, level="warn")
3652
+
3563
3653
  @staticmethod
3564
3654
  def _footer_server_messages(
3565
3655
  server_info_response: Optional[ServerInfoResponse] = None,