skypilot-nightly 1.0.0.dev20250827__py3-none-any.whl → 1.0.0.dev20250828__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of skypilot-nightly might be problematic. Click here for more details.

Files changed (66) hide show
  1. sky/__init__.py +2 -2
  2. sky/admin_policy.py +11 -10
  3. sky/authentication.py +1 -1
  4. sky/backends/backend.py +3 -5
  5. sky/backends/backend_utils.py +11 -13
  6. sky/backends/cloud_vm_ray_backend.py +11 -22
  7. sky/backends/local_docker_backend.py +3 -8
  8. sky/client/cli/command.py +41 -9
  9. sky/client/sdk.py +23 -8
  10. sky/client/sdk_async.py +6 -2
  11. sky/core.py +1 -4
  12. sky/dashboard/out/404.html +1 -1
  13. sky/dashboard/out/_next/static/chunks/{webpack-6e76f636a048e145.js → webpack-6dae1cd599a34def.js} +1 -1
  14. sky/dashboard/out/clusters/[cluster]/[job].html +1 -1
  15. sky/dashboard/out/clusters/[cluster].html +1 -1
  16. sky/dashboard/out/clusters.html +1 -1
  17. sky/dashboard/out/config.html +1 -1
  18. sky/dashboard/out/index.html +1 -1
  19. sky/dashboard/out/infra/[context].html +1 -1
  20. sky/dashboard/out/infra.html +1 -1
  21. sky/dashboard/out/jobs/[job].html +1 -1
  22. sky/dashboard/out/jobs/pools/[pool].html +1 -1
  23. sky/dashboard/out/jobs.html +1 -1
  24. sky/dashboard/out/users.html +1 -1
  25. sky/dashboard/out/volumes.html +1 -1
  26. sky/dashboard/out/workspace/new.html +1 -1
  27. sky/dashboard/out/workspaces/[name].html +1 -1
  28. sky/dashboard/out/workspaces.html +1 -1
  29. sky/global_user_state.py +24 -12
  30. sky/jobs/client/sdk.py +5 -2
  31. sky/jobs/recovery_strategy.py +9 -4
  32. sky/logs/agent.py +2 -2
  33. sky/logs/aws.py +6 -3
  34. sky/provision/do/utils.py +2 -1
  35. sky/provision/kubernetes/instance.py +55 -11
  36. sky/provision/kubernetes/utils.py +2 -2
  37. sky/provision/nebius/utils.py +36 -2
  38. sky/serve/client/impl.py +5 -4
  39. sky/serve/replica_managers.py +4 -3
  40. sky/serve/serve_utils.py +2 -2
  41. sky/serve/server/impl.py +3 -2
  42. sky/server/auth/oauth2_proxy.py +10 -4
  43. sky/server/common.py +3 -2
  44. sky/server/daemons.py +10 -5
  45. sky/server/requests/executor.py +2 -1
  46. sky/server/requests/requests.py +21 -0
  47. sky/server/server.py +16 -0
  48. sky/skylet/events.py +2 -3
  49. sky/skypilot_config.py +10 -10
  50. sky/task.py +1 -1
  51. sky/templates/nebius-ray.yml.j2 +4 -8
  52. sky/usage/usage_lib.py +3 -2
  53. sky/utils/common_utils.py +0 -72
  54. sky/utils/controller_utils.py +4 -3
  55. sky/utils/dag_utils.py +4 -4
  56. sky/utils/kubernetes/config_map_utils.py +3 -3
  57. sky/utils/schemas.py +3 -0
  58. sky/utils/yaml_utils.py +77 -10
  59. {skypilot_nightly-1.0.0.dev20250827.dist-info → skypilot_nightly-1.0.0.dev20250828.dist-info}/METADATA +1 -1
  60. {skypilot_nightly-1.0.0.dev20250827.dist-info → skypilot_nightly-1.0.0.dev20250828.dist-info}/RECORD +66 -66
  61. /sky/dashboard/out/_next/static/{-eL7Ky3bxVivzeLHNB9U6 → 9DW6d9jaP2kZt0NcgIfFa}/_buildManifest.js +0 -0
  62. /sky/dashboard/out/_next/static/{-eL7Ky3bxVivzeLHNB9U6 → 9DW6d9jaP2kZt0NcgIfFa}/_ssgManifest.js +0 -0
  63. {skypilot_nightly-1.0.0.dev20250827.dist-info → skypilot_nightly-1.0.0.dev20250828.dist-info}/WHEEL +0 -0
  64. {skypilot_nightly-1.0.0.dev20250827.dist-info → skypilot_nightly-1.0.0.dev20250828.dist-info}/entry_points.txt +0 -0
  65. {skypilot_nightly-1.0.0.dev20250827.dist-info → skypilot_nightly-1.0.0.dev20250828.dist-info}/licenses/LICENSE +0 -0
  66. {skypilot_nightly-1.0.0.dev20250827.dist-info → skypilot_nightly-1.0.0.dev20250828.dist-info}/top_level.txt +0 -0
sky/usage/usage_lib.py CHANGED
@@ -19,6 +19,7 @@ from sky.usage import constants
19
19
  from sky.utils import common_utils
20
20
  from sky.utils import env_options
21
21
  from sky.utils import ux_utils
22
+ from sky.utils import yaml_utils
22
23
 
23
24
  if typing.TYPE_CHECKING:
24
25
  import inspect
@@ -402,7 +403,7 @@ def _clean_yaml(yaml_info: Dict[str, Optional[str]]):
402
403
  contents = inspect.getsource(contents)
403
404
 
404
405
  if type(contents) in constants.USAGE_MESSAGE_REDACT_TYPES:
405
- lines = common_utils.dump_yaml_str({
406
+ lines = yaml_utils.dump_yaml_str({
406
407
  redact_type: contents
407
408
  }).strip().split('\n')
408
409
  message = (f'{len(lines)} lines {redact_type.upper()}'
@@ -431,7 +432,7 @@ def prepare_json_from_yaml_config(
431
432
  with open(yaml_config_or_path, 'r', encoding='utf-8') as f:
432
433
  lines = f.readlines()
433
434
  comment_lines = [line for line in lines if line.startswith('#')]
434
- yaml_info = common_utils.read_yaml_all(yaml_config_or_path)
435
+ yaml_info = yaml_utils.read_yaml_all(yaml_config_or_path)
435
436
 
436
437
  for i in range(len(yaml_info)):
437
438
  if yaml_info[i] is None:
sky/utils/common_utils.py CHANGED
@@ -6,7 +6,6 @@ import functools
6
6
  import getpass
7
7
  import hashlib
8
8
  import inspect
9
- import io
10
9
  import os
11
10
  import platform
12
11
  import random
@@ -30,16 +29,13 @@ from sky.usage import constants as usage_constants
30
29
  from sky.utils import annotations
31
30
  from sky.utils import ux_utils
32
31
  from sky.utils import validator
33
- from sky.utils import yaml_utils
34
32
 
35
33
  if typing.TYPE_CHECKING:
36
34
  import jinja2
37
35
  import psutil
38
- import yaml
39
36
  else:
40
37
  jinja2 = adaptors_common.LazyImport('jinja2')
41
38
  psutil = adaptors_common.LazyImport('psutil')
42
- yaml = adaptors_common.LazyImport('yaml')
43
39
 
44
40
  USER_HASH_FILE = os.path.expanduser('~/.sky/user_hash')
45
41
  USER_HASH_LENGTH = 8
@@ -574,74 +570,6 @@ def user_and_hostname_hash() -> str:
574
570
  return f'{getpass.getuser()}-{hostname_hash}'
575
571
 
576
572
 
577
- def read_yaml(path: Optional[str]) -> Dict[str, Any]:
578
- if path is None:
579
- raise ValueError('Attempted to read a None YAML.')
580
- with open(path, 'r', encoding='utf-8') as f:
581
- config = yaml_utils.safe_load(f)
582
- return config
583
-
584
-
585
- def read_yaml_all_str(yaml_str: str) -> List[Dict[str, Any]]:
586
- stream = io.StringIO(yaml_str)
587
- config = yaml_utils.safe_load_all(stream)
588
- configs = list(config)
589
- if not configs:
590
- # Empty YAML file.
591
- return [{}]
592
- return configs
593
-
594
-
595
- def read_yaml_all(path: str) -> List[Dict[str, Any]]:
596
- with open(path, 'r', encoding='utf-8') as f:
597
- return read_yaml_all_str(f.read())
598
-
599
-
600
- def dump_yaml(path: str,
601
- config: Union[List[Dict[str, Any]], Dict[str, Any]],
602
- blank: bool = False) -> None:
603
- """Dumps a YAML file.
604
-
605
- Args:
606
- path: the path to the YAML file.
607
- config: the configuration to dump.
608
- """
609
- with open(path, 'w', encoding='utf-8') as f:
610
- contents = dump_yaml_str(config)
611
- if blank and isinstance(config, dict) and len(config) == 0:
612
- # when dumping to yaml, an empty dict will go in as {}.
613
- contents = ''
614
- f.write(contents)
615
-
616
-
617
- def dump_yaml_str(config: Union[List[Dict[str, Any]], Dict[str, Any]]) -> str:
618
- """Dumps a YAML string.
619
-
620
- Args:
621
- config: the configuration to dump.
622
-
623
- Returns:
624
- The YAML string.
625
- """
626
-
627
- # https://github.com/yaml/pyyaml/issues/127
628
- class LineBreakDumper(yaml.SafeDumper):
629
-
630
- def write_line_break(self, data=None):
631
- super().write_line_break(data)
632
- if len(self.indents) == 1:
633
- super().write_line_break()
634
-
635
- if isinstance(config, list):
636
- dump_func = yaml.dump_all # type: ignore
637
- else:
638
- dump_func = yaml.dump # type: ignore
639
- return dump_func(config,
640
- Dumper=LineBreakDumper,
641
- sort_keys=False,
642
- default_flow_style=False)
643
-
644
-
645
573
  def make_decorator(cls, name_or_fn: Union[str, Callable],
646
574
  **ctx_kwargs) -> Callable:
647
575
  """Make the cls a decorator.
@@ -38,6 +38,7 @@ from sky.utils import env_options
38
38
  from sky.utils import registry
39
39
  from sky.utils import rich_utils
40
40
  from sky.utils import ux_utils
41
+ from sky.utils import yaml_utils
41
42
 
42
43
  if typing.TYPE_CHECKING:
43
44
  import psutil
@@ -497,7 +498,7 @@ def shared_controller_vars_to_fill(
497
498
  with tempfile.NamedTemporaryFile(
498
499
  delete=False,
499
500
  suffix=_LOCAL_SKYPILOT_CONFIG_PATH_SUFFIX) as temp_file:
500
- common_utils.dump_yaml(temp_file.name, dict(**local_user_config))
501
+ yaml_utils.dump_yaml(temp_file.name, dict(**local_user_config))
501
502
  local_user_config_path = temp_file.name
502
503
 
503
504
  vars_to_fill: Dict[str, Any] = {
@@ -786,9 +787,9 @@ def replace_skypilot_config_path_in_file_mounts(
786
787
  continue
787
788
  if local_path.endswith(_LOCAL_SKYPILOT_CONFIG_PATH_SUFFIX):
788
789
  with tempfile.NamedTemporaryFile('w', delete=False) as f:
789
- user_config = common_utils.read_yaml(local_path)
790
+ user_config = yaml_utils.read_yaml(local_path)
790
791
  config = _setup_proxy_command_on_controller(cloud, user_config)
791
- common_utils.dump_yaml(f.name, dict(**config))
792
+ yaml_utils.dump_yaml(f.name, dict(**config))
792
793
  file_mounts[remote_path] = f.name
793
794
  replaced = True
794
795
  if replaced:
sky/utils/dag_utils.py CHANGED
@@ -6,9 +6,9 @@ from sky import dag as dag_lib
6
6
  from sky import sky_logging
7
7
  from sky import task as task_lib
8
8
  from sky.utils import cluster_utils
9
- from sky.utils import common_utils
10
9
  from sky.utils import registry
11
10
  from sky.utils import ux_utils
11
+ from sky.utils import yaml_utils
12
12
 
13
13
  logger = sky_logging.init_logger(__name__)
14
14
 
@@ -117,7 +117,7 @@ def load_chain_dag_from_yaml(
117
117
  A chain Dag with 1 or more tasks (an empty entrypoint would create a
118
118
  trivial task).
119
119
  """
120
- configs = common_utils.read_yaml_all(path)
120
+ configs = yaml_utils.read_yaml_all(path)
121
121
  return _load_chain_dag(configs, env_overrides, secret_overrides)
122
122
 
123
123
 
@@ -143,7 +143,7 @@ def load_chain_dag_from_yaml_str(
143
143
  A chain Dag with 1 or more tasks (an empty entrypoint would create a
144
144
  trivial task).
145
145
  """
146
- configs = common_utils.read_yaml_all_str(yaml_str)
146
+ configs = yaml_utils.read_yaml_all_str(yaml_str)
147
147
  return _load_chain_dag(configs, env_overrides, secrets_overrides)
148
148
 
149
149
 
@@ -164,7 +164,7 @@ def dump_chain_dag_to_yaml_str(dag: dag_lib.Dag,
164
164
  configs.append(
165
165
  task.to_yaml_config(
166
166
  use_user_specified_yaml=use_user_specified_yaml))
167
- return common_utils.dump_yaml_str(configs)
167
+ return yaml_utils.dump_yaml_str(configs)
168
168
 
169
169
 
170
170
  def dump_chain_dag_to_yaml(dag: dag_lib.Dag, path: str) -> None:
@@ -4,7 +4,7 @@ import os
4
4
  from sky import sky_logging
5
5
  from sky import skypilot_config
6
6
  from sky.adaptors import kubernetes
7
- from sky.utils import common_utils
7
+ from sky.utils import yaml_utils
8
8
 
9
9
  logger = sky_logging.init_logger(__name__)
10
10
 
@@ -69,7 +69,7 @@ def initialize_configmap_sync_on_startup(config_file_path: str) -> None:
69
69
 
70
70
  current_config = skypilot_config.parse_and_validate_config_file(
71
71
  config_file_path)
72
- config_yaml = common_utils.dump_yaml_str(dict(current_config))
72
+ config_yaml = yaml_utils.dump_yaml_str(dict(current_config))
73
73
 
74
74
  configmap_body = {
75
75
  'apiVersion': 'v1',
@@ -111,7 +111,7 @@ def patch_configmap_with_config(config, config_file_path: str) -> None:
111
111
  try:
112
112
  namespace = _get_kubernetes_namespace()
113
113
  configmap_name = _get_configmap_name()
114
- config_yaml = common_utils.dump_yaml_str(dict(config))
114
+ config_yaml = yaml_utils.dump_yaml_str(dict(config))
115
115
  patch_body = {'data': {'config.yaml': config_yaml}}
116
116
 
117
117
  try:
sky/utils/schemas.py CHANGED
@@ -1555,6 +1555,9 @@ def get_config_schema():
1555
1555
  'cluster_event_retention_hours': {
1556
1556
  'type': 'number',
1557
1557
  },
1558
+ 'cluster_debug_event_retention_hours': {
1559
+ 'type': 'number',
1560
+ },
1558
1561
  }
1559
1562
  }
1560
1563
 
sky/utils/yaml_utils.py CHANGED
@@ -1,5 +1,6 @@
1
1
  """YAML utilities."""
2
- from typing import Any, TYPE_CHECKING
2
+ import io
3
+ from typing import Any, Dict, List, Optional, TYPE_CHECKING, Union
3
4
 
4
5
  from sky.adaptors import common
5
6
 
@@ -8,28 +9,94 @@ if TYPE_CHECKING:
8
9
  else:
9
10
  yaml = common.LazyImport('yaml')
10
11
 
11
- _csafe_loader_import_error = False
12
+ _c_extension_unavailable = False
12
13
 
13
14
 
14
15
  def safe_load(stream) -> Any:
15
- global _csafe_loader_import_error
16
- if _csafe_loader_import_error:
16
+ global _c_extension_unavailable
17
+ if _c_extension_unavailable:
17
18
  return yaml.load(stream, Loader=yaml.SafeLoader)
18
19
 
19
20
  try:
20
21
  return yaml.load(stream, Loader=yaml.CSafeLoader)
21
- except ImportError:
22
- _csafe_loader_import_error = True
22
+ except AttributeError:
23
+ _c_extension_unavailable = True
23
24
  return yaml.load(stream, Loader=yaml.SafeLoader)
24
25
 
25
26
 
26
27
  def safe_load_all(stream) -> Any:
27
- global _csafe_loader_import_error
28
- if _csafe_loader_import_error:
28
+ global _c_extension_unavailable
29
+ if _c_extension_unavailable:
29
30
  return yaml.load_all(stream, Loader=yaml.SafeLoader)
30
31
 
31
32
  try:
32
33
  return yaml.load_all(stream, Loader=yaml.CSafeLoader)
33
- except ImportError:
34
- _csafe_loader_import_error = True
34
+ except AttributeError:
35
+ _c_extension_unavailable = True
35
36
  return yaml.load_all(stream, Loader=yaml.SafeLoader)
37
+
38
+
39
+ def read_yaml(path: Optional[str]) -> Dict[str, Any]:
40
+ if path is None:
41
+ raise ValueError('Attempted to read a None YAML.')
42
+ with open(path, 'r', encoding='utf-8') as f:
43
+ config = safe_load(f)
44
+ return config
45
+
46
+
47
+ def read_yaml_all_str(yaml_str: str) -> List[Dict[str, Any]]:
48
+ stream = io.StringIO(yaml_str)
49
+ config = safe_load_all(stream)
50
+ configs = list(config)
51
+ if not configs:
52
+ # Empty YAML file.
53
+ return [{}]
54
+ return configs
55
+
56
+
57
+ def read_yaml_all(path: str) -> List[Dict[str, Any]]:
58
+ with open(path, 'r', encoding='utf-8') as f:
59
+ return read_yaml_all_str(f.read())
60
+
61
+
62
+ def dump_yaml(path: str,
63
+ config: Union[List[Dict[str, Any]], Dict[str, Any]],
64
+ blank: bool = False) -> None:
65
+ """Dumps a YAML file.
66
+
67
+ Args:
68
+ path: the path to the YAML file.
69
+ config: the configuration to dump.
70
+ """
71
+ with open(path, 'w', encoding='utf-8') as f:
72
+ contents = dump_yaml_str(config)
73
+ if blank and isinstance(config, dict) and len(config) == 0:
74
+ # when dumping to yaml, an empty dict will go in as {}.
75
+ contents = ''
76
+ f.write(contents)
77
+
78
+
79
+ def dump_yaml_str(config: Union[List[Dict[str, Any]], Dict[str, Any]]) -> str:
80
+ """Dumps a YAML string.
81
+ Args:
82
+ config: the configuration to dump.
83
+ Returns:
84
+ The YAML string.
85
+ """
86
+
87
+ # https://github.com/yaml/pyyaml/issues/127
88
+ class LineBreakDumper(yaml.SafeDumper):
89
+
90
+ def write_line_break(self, data=None):
91
+ super().write_line_break(data)
92
+ if len(self.indents) == 1:
93
+ super().write_line_break()
94
+
95
+ if isinstance(config, list):
96
+ dump_func = yaml.dump_all # type: ignore
97
+ else:
98
+ dump_func = yaml.dump # type: ignore
99
+ return dump_func(config,
100
+ Dumper=LineBreakDumper,
101
+ sort_keys=False,
102
+ default_flow_style=False)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: skypilot-nightly
3
- Version: 1.0.0.dev20250827
3
+ Version: 1.0.0.dev20250828
4
4
  Summary: SkyPilot: Run AI on Any Infra — Unified, Faster, Cheaper.
5
5
  Author: SkyPilot Team
6
6
  License: Apache 2.0