skypilot-nightly 1.0.0.dev20250323__py3-none-any.whl → 1.0.0.dev20250325__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.
- sky/__init__.py +2 -2
- sky/adaptors/common.py +11 -7
- sky/adaptors/ibm.py +3 -3
- sky/authentication.py +14 -4
- sky/backends/backend_utils.py +14 -5
- sky/backends/cloud_vm_ray_backend.py +26 -4
- sky/client/common.py +8 -4
- sky/client/sdk.py +8 -3
- sky/clouds/fluidstack.py +5 -2
- sky/clouds/lambda_cloud.py +5 -2
- sky/clouds/paperspace.py +5 -2
- sky/clouds/service_catalog/common.py +2 -1
- sky/clouds/utils/scp_utils.py +8 -2
- sky/clouds/vsphere.py +5 -2
- sky/jobs/client/sdk.py +5 -1
- sky/jobs/scheduler.py +7 -1
- sky/jobs/utils.py +5 -1
- sky/optimizer.py +2 -1
- sky/provision/fluidstack/fluidstack_utils.py +7 -2
- sky/provision/gcp/constants.py +0 -6
- sky/provision/kubernetes/config.py +7 -2
- sky/provision/kubernetes/network_utils.py +9 -3
- sky/provision/kubernetes/utils.py +7 -3
- sky/provision/lambda_cloud/lambda_utils.py +8 -3
- sky/provision/paperspace/utils.py +8 -3
- sky/provision/vsphere/common/ssl_helper.py +7 -2
- sky/provision/vsphere/common/vapiconnect.py +8 -1
- sky/provision/vsphere/vsphere_utils.py +7 -2
- sky/serve/client/sdk.py +5 -1
- sky/serve/serve_utils.py +16 -6
- sky/serve/service.py +2 -1
- sky/serve/service_spec.py +7 -2
- sky/server/common.py +10 -5
- sky/server/requests/payloads.py +7 -2
- sky/server/requests/requests.py +3 -1
- sky/skylet/autostop_lib.py +7 -2
- sky/skylet/job_lib.py +7 -1
- sky/skypilot_config.py +7 -2
- sky/task.py +5 -1
- sky/utils/common_utils.py +14 -6
- sky/utils/log_utils.py +9 -3
- sky/utils/rich_console_utils.py +21 -0
- sky/utils/rich_utils.py +29 -13
- sky/utils/subprocess_utils.py +7 -1
- sky/utils/ux_utils.py +2 -4
- sky/utils/validator.py +14 -4
- {skypilot_nightly-1.0.0.dev20250323.dist-info → skypilot_nightly-1.0.0.dev20250325.dist-info}/METADATA +1 -1
- {skypilot_nightly-1.0.0.dev20250323.dist-info → skypilot_nightly-1.0.0.dev20250325.dist-info}/RECORD +52 -51
- {skypilot_nightly-1.0.0.dev20250323.dist-info → skypilot_nightly-1.0.0.dev20250325.dist-info}/WHEEL +1 -1
- {skypilot_nightly-1.0.0.dev20250323.dist-info → skypilot_nightly-1.0.0.dev20250325.dist-info}/entry_points.txt +0 -0
- {skypilot_nightly-1.0.0.dev20250323.dist-info → skypilot_nightly-1.0.0.dev20250325.dist-info}/licenses/LICENSE +0 -0
- {skypilot_nightly-1.0.0.dev20250323.dist-info → skypilot_nightly-1.0.0.dev20250325.dist-info}/top_level.txt +0 -0
@@ -3,14 +3,19 @@
|
|
3
3
|
import json
|
4
4
|
import os
|
5
5
|
import time
|
6
|
+
import typing
|
6
7
|
from typing import Any, Dict, List, Optional, Union
|
7
8
|
|
8
|
-
import requests
|
9
|
-
|
10
9
|
from sky import sky_logging
|
10
|
+
from sky.adaptors import common as adaptors_common
|
11
11
|
import sky.provision.paperspace.constants as constants
|
12
12
|
from sky.utils import common_utils
|
13
13
|
|
14
|
+
if typing.TYPE_CHECKING:
|
15
|
+
import requests
|
16
|
+
else:
|
17
|
+
requests = adaptors_common.LazyImport('requests')
|
18
|
+
|
14
19
|
logger = sky_logging.init_logger(__name__)
|
15
20
|
|
16
21
|
CREDENTIALS_PATH = '~/.paperspace/config.json'
|
@@ -25,7 +30,7 @@ class PaperspaceCloudError(Exception):
|
|
25
30
|
pass
|
26
31
|
|
27
32
|
|
28
|
-
def raise_paperspace_api_error(response: requests.Response) -> None:
|
33
|
+
def raise_paperspace_api_error(response: 'requests.Response') -> None:
|
29
34
|
"""Raise PaperspaceCloudError if appropriate."""
|
30
35
|
status_code = response.status_code
|
31
36
|
if status_code == 200:
|
@@ -1,9 +1,14 @@
|
|
1
1
|
"""SSL Helper
|
2
2
|
"""
|
3
|
-
|
4
3
|
import ssl
|
4
|
+
import typing
|
5
|
+
|
6
|
+
from sky.adaptors import common as adaptors_common
|
5
7
|
|
6
|
-
|
8
|
+
if typing.TYPE_CHECKING:
|
9
|
+
import requests
|
10
|
+
else:
|
11
|
+
requests = adaptors_common.LazyImport('requests')
|
7
12
|
|
8
13
|
|
9
14
|
def get_unverified_context():
|
@@ -1,11 +1,18 @@
|
|
1
1
|
"""Vapi Connect
|
2
2
|
"""
|
3
3
|
|
4
|
-
import
|
4
|
+
import typing
|
5
|
+
|
5
6
|
from urllib3.exceptions import InsecureRequestWarning
|
6
7
|
|
8
|
+
from sky.adaptors import common as adaptors_common
|
7
9
|
from sky.adaptors import vsphere as vsphere_adaptor
|
8
10
|
|
11
|
+
if typing.TYPE_CHECKING:
|
12
|
+
import requests
|
13
|
+
else:
|
14
|
+
requests = adaptors_common.LazyImport('requests')
|
15
|
+
|
9
16
|
|
10
17
|
def get_jsonrpc_endpoint_url(host):
|
11
18
|
# The URL for the stub requests are made against the /api HTTP endpoint
|
@@ -3,12 +3,12 @@
|
|
3
3
|
import http.cookies as http_cookies
|
4
4
|
import os
|
5
5
|
import ssl
|
6
|
+
import typing
|
6
7
|
from typing import Any, Dict, List, Optional
|
7
8
|
|
8
|
-
import yaml
|
9
|
-
|
10
9
|
from sky import exceptions
|
11
10
|
from sky import sky_logging
|
11
|
+
from sky.adaptors import common as adaptors_common
|
12
12
|
from sky.adaptors import vsphere as vsphere_adaptor
|
13
13
|
from sky.clouds.service_catalog import vsphere_catalog
|
14
14
|
from sky.clouds.service_catalog.common import get_catalog_path
|
@@ -33,6 +33,11 @@ from sky.provision.vsphere.common.vim_utils import poweron_vm
|
|
33
33
|
from sky.provision.vsphere.common.vim_utils import wait_for_tasks
|
34
34
|
from sky.provision.vsphere.common.vim_utils import wait_internal_ip_ready
|
35
35
|
|
36
|
+
if typing.TYPE_CHECKING:
|
37
|
+
import yaml
|
38
|
+
else:
|
39
|
+
yaml = adaptors_common.LazyImport('yaml')
|
40
|
+
|
36
41
|
logger = sky_logging.init_logger(__name__)
|
37
42
|
|
38
43
|
CREDENTIALS_PATH = '~/.vsphere/credential.yaml'
|
sky/serve/client/sdk.py
CHANGED
@@ -4,8 +4,8 @@ import typing
|
|
4
4
|
from typing import List, Optional, Union
|
5
5
|
|
6
6
|
import click
|
7
|
-
import requests
|
8
7
|
|
8
|
+
from sky.adaptors import common as adaptors_common
|
9
9
|
from sky.client import common as client_common
|
10
10
|
from sky.server import common as server_common
|
11
11
|
from sky.server.requests import payloads
|
@@ -15,8 +15,12 @@ from sky.utils import dag_utils
|
|
15
15
|
if typing.TYPE_CHECKING:
|
16
16
|
import io
|
17
17
|
|
18
|
+
import requests
|
19
|
+
|
18
20
|
import sky
|
19
21
|
from sky.serve import serve_utils
|
22
|
+
else:
|
23
|
+
requests = adaptors_common.LazyImport('requests')
|
20
24
|
|
21
25
|
|
22
26
|
@usage_lib.entrypoint
|
sky/serve/serve_utils.py
CHANGED
@@ -18,16 +18,16 @@ import uuid
|
|
18
18
|
|
19
19
|
import colorama
|
20
20
|
import filelock
|
21
|
-
import psutil
|
22
|
-
import requests
|
23
21
|
|
24
22
|
from sky import backends
|
25
23
|
from sky import exceptions
|
26
24
|
from sky import global_user_state
|
25
|
+
from sky.adaptors import common as adaptors_common
|
27
26
|
from sky.serve import constants
|
28
27
|
from sky.serve import serve_state
|
29
28
|
from sky.skylet import constants as skylet_constants
|
30
29
|
from sky.skylet import job_lib
|
30
|
+
from sky.utils import annotations
|
31
31
|
from sky.utils import common_utils
|
32
32
|
from sky.utils import log_utils
|
33
33
|
from sky.utils import message_utils
|
@@ -37,12 +37,22 @@ from sky.utils import ux_utils
|
|
37
37
|
|
38
38
|
if typing.TYPE_CHECKING:
|
39
39
|
import fastapi
|
40
|
+
import psutil
|
41
|
+
import requests
|
40
42
|
|
41
43
|
from sky.serve import replica_managers
|
44
|
+
else:
|
45
|
+
psutil = adaptors_common.LazyImport('psutil')
|
46
|
+
requests = adaptors_common.LazyImport('requests')
|
47
|
+
|
48
|
+
|
49
|
+
@annotations.lru_cache(scope='request')
|
50
|
+
def get_num_service_threshold():
|
51
|
+
"""Get number of services threshold, calculating it only when needed."""
|
52
|
+
system_memory_gb = psutil.virtual_memory().total // (1024**3)
|
53
|
+
return system_memory_gb // constants.CONTROLLER_MEMORY_USAGE_GB
|
54
|
+
|
42
55
|
|
43
|
-
_SYSTEM_MEMORY_GB = psutil.virtual_memory().total // (1024**3)
|
44
|
-
NUM_SERVICE_THRESHOLD = (_SYSTEM_MEMORY_GB //
|
45
|
-
constants.CONTROLLER_MEMORY_USAGE_GB)
|
46
56
|
_CONTROLLER_URL = 'http://localhost:{CONTROLLER_PORT}'
|
47
57
|
|
48
58
|
# NOTE(dev): We assume log paths are either in ~/sky_logs/... or ~/.sky/...
|
@@ -607,7 +617,7 @@ def wait_service_registration(service_name: str, job_id: int) -> str:
|
|
607
617
|
lb_port = record['load_balancer_port']
|
608
618
|
if lb_port is not None:
|
609
619
|
return message_utils.encode_payload(lb_port)
|
610
|
-
elif len(serve_state.get_services()) >=
|
620
|
+
elif len(serve_state.get_services()) >= get_num_service_threshold():
|
611
621
|
with ux_utils.print_exception_no_traceback():
|
612
622
|
raise RuntimeError('Max number of services reached. '
|
613
623
|
'To spin up more services, please '
|
sky/serve/service.py
CHANGED
@@ -147,7 +147,8 @@ def _start(service_name: str, tmp_task_yaml: str, job_id: int):
|
|
147
147
|
# Already checked before submit to controller.
|
148
148
|
assert task.service is not None, task
|
149
149
|
service_spec = task.service
|
150
|
-
if len(serve_state.get_services()) >=
|
150
|
+
if (len(serve_state.get_services()) >=
|
151
|
+
serve_utils.get_num_service_threshold()):
|
151
152
|
cleanup_storage(tmp_task_yaml)
|
152
153
|
with ux_utils.print_exception_no_traceback():
|
153
154
|
raise RuntimeError('Max number of services reached.')
|
sky/serve/service_spec.py
CHANGED
@@ -2,11 +2,11 @@
|
|
2
2
|
import json
|
3
3
|
import os
|
4
4
|
import textwrap
|
5
|
+
import typing
|
5
6
|
from typing import Any, Dict, List, Optional
|
6
7
|
|
7
|
-
import yaml
|
8
|
-
|
9
8
|
from sky import serve
|
9
|
+
from sky.adaptors import common as adaptors_common
|
10
10
|
from sky.serve import constants
|
11
11
|
from sky.serve import load_balancing_policies as lb_policies
|
12
12
|
from sky.serve import serve_utils
|
@@ -14,6 +14,11 @@ from sky.utils import common_utils
|
|
14
14
|
from sky.utils import schemas
|
15
15
|
from sky.utils import ux_utils
|
16
16
|
|
17
|
+
if typing.TYPE_CHECKING:
|
18
|
+
import yaml
|
19
|
+
else:
|
20
|
+
yaml = adaptors_common.LazyImport('yaml')
|
21
|
+
|
17
22
|
|
18
23
|
class SkyServiceSpec:
|
19
24
|
"""SkyServe service specification."""
|
sky/server/common.py
CHANGED
@@ -15,12 +15,11 @@ import uuid
|
|
15
15
|
|
16
16
|
import colorama
|
17
17
|
import filelock
|
18
|
-
import pydantic
|
19
|
-
import requests
|
20
18
|
|
21
19
|
from sky import exceptions
|
22
20
|
from sky import sky_logging
|
23
21
|
from sky import skypilot_config
|
22
|
+
from sky.adaptors import common as adaptors_common
|
24
23
|
from sky.data import data_utils
|
25
24
|
from sky.server import constants as server_constants
|
26
25
|
from sky.skylet import constants
|
@@ -31,7 +30,13 @@ from sky.utils import rich_utils
|
|
31
30
|
from sky.utils import ux_utils
|
32
31
|
|
33
32
|
if typing.TYPE_CHECKING:
|
33
|
+
import pydantic
|
34
|
+
import requests
|
35
|
+
|
34
36
|
from sky import dag as dag_lib
|
37
|
+
else:
|
38
|
+
pydantic = adaptors_common.LazyImport('pydantic')
|
39
|
+
requests = adaptors_common.LazyImport('requests')
|
35
40
|
|
36
41
|
DEFAULT_SERVER_URL = 'http://127.0.0.1:46580'
|
37
42
|
AVAILBLE_LOCAL_API_SERVER_HOSTS = ['0.0.0.0', 'localhost', '127.0.0.1']
|
@@ -145,7 +150,7 @@ def get_api_server_status(endpoint: Optional[str] = None) -> ApiServerInfo:
|
|
145
150
|
return ApiServerInfo(status=ApiServerStatus.UNHEALTHY, api_version=None)
|
146
151
|
|
147
152
|
|
148
|
-
def handle_request_error(response: requests.Response) -> None:
|
153
|
+
def handle_request_error(response: 'requests.Response') -> None:
|
149
154
|
if response.status_code != 200:
|
150
155
|
with ux_utils.print_exception_no_traceback():
|
151
156
|
raise RuntimeError(
|
@@ -155,7 +160,7 @@ def handle_request_error(response: requests.Response) -> None:
|
|
155
160
|
f'{response.text}')
|
156
161
|
|
157
162
|
|
158
|
-
def get_request_id(response: requests.Response) -> RequestId:
|
163
|
+
def get_request_id(response: 'requests.Response') -> RequestId:
|
159
164
|
handle_request_error(response)
|
160
165
|
request_id = response.headers.get('X-Request-ID')
|
161
166
|
if request_id is None:
|
@@ -398,7 +403,7 @@ def api_server_user_logs_dir_prefix(
|
|
398
403
|
return API_SERVER_CLIENT_DIR / user_hash / 'sky_logs'
|
399
404
|
|
400
405
|
|
401
|
-
def request_body_to_params(body: pydantic.BaseModel) -> Dict[str, Any]:
|
406
|
+
def request_body_to_params(body: 'pydantic.BaseModel') -> Dict[str, Any]:
|
402
407
|
return {
|
403
408
|
k: v for k, v in body.model_dump(mode='json').items() if v is not None
|
404
409
|
}
|
sky/server/requests/payloads.py
CHANGED
@@ -8,14 +8,14 @@ payloads is that a user can find the default values in the Restful API docs.
|
|
8
8
|
import getpass
|
9
9
|
import json
|
10
10
|
import os
|
11
|
+
import typing
|
11
12
|
from typing import Any, Dict, List, Optional, Tuple, Union
|
12
13
|
|
13
|
-
import pydantic
|
14
|
-
|
15
14
|
from sky import admin_policy
|
16
15
|
from sky import serve
|
17
16
|
from sky import sky_logging
|
18
17
|
from sky import skypilot_config
|
18
|
+
from sky.adaptors import common as adaptors_common
|
19
19
|
from sky.server import common
|
20
20
|
from sky.skylet import constants
|
21
21
|
from sky.usage import constants as usage_constants
|
@@ -25,6 +25,11 @@ from sky.utils import common as common_lib
|
|
25
25
|
from sky.utils import common_utils
|
26
26
|
from sky.utils import registry
|
27
27
|
|
28
|
+
if typing.TYPE_CHECKING:
|
29
|
+
import pydantic
|
30
|
+
else:
|
31
|
+
pydantic = adaptors_common.LazyImport('pydantic')
|
32
|
+
|
28
33
|
logger = sky_logging.init_logger(__name__)
|
29
34
|
|
30
35
|
|
sky/server/requests/requests.py
CHANGED
@@ -396,7 +396,6 @@ pathlib.Path(_DB_PATH).parents[0].mkdir(parents=True, exist_ok=True)
|
|
396
396
|
|
397
397
|
|
398
398
|
def create_table(cursor, conn):
|
399
|
-
del conn
|
400
399
|
# Enable WAL mode to avoid locking issues.
|
401
400
|
# See: issue #1441 and PR #1509
|
402
401
|
# https://github.com/microsoft/WSL/issues/2395
|
@@ -428,6 +427,9 @@ def create_table(cursor, conn):
|
|
428
427
|
{COL_USER_ID} TEXT,
|
429
428
|
{COL_STATUS_MSG} TEXT)""")
|
430
429
|
|
430
|
+
db_utils.add_column_to_table(cursor, conn, REQUEST_TABLE, COL_STATUS_MSG,
|
431
|
+
'TEXT')
|
432
|
+
|
431
433
|
|
432
434
|
_DB = None
|
433
435
|
|
sky/skylet/autostop_lib.py
CHANGED
@@ -2,15 +2,20 @@
|
|
2
2
|
import pickle
|
3
3
|
import shlex
|
4
4
|
import time
|
5
|
+
import typing
|
5
6
|
from typing import List, Optional
|
6
7
|
|
7
|
-
import psutil
|
8
|
-
|
9
8
|
from sky import sky_logging
|
9
|
+
from sky.adaptors import common as adaptors_common
|
10
10
|
from sky.skylet import configs
|
11
11
|
from sky.skylet import constants
|
12
12
|
from sky.utils import message_utils
|
13
13
|
|
14
|
+
if typing.TYPE_CHECKING:
|
15
|
+
import psutil
|
16
|
+
else:
|
17
|
+
psutil = adaptors_common.LazyImport('psutil')
|
18
|
+
|
14
19
|
logger = sky_logging.init_logger(__name__)
|
15
20
|
|
16
21
|
_AUTOSTOP_CONFIG_KEY = 'autostop_config'
|
sky/skylet/job_lib.py
CHANGED
@@ -11,14 +11,15 @@ import shlex
|
|
11
11
|
import signal
|
12
12
|
import sqlite3
|
13
13
|
import time
|
14
|
+
import typing
|
14
15
|
from typing import Any, Dict, List, Optional, Sequence
|
15
16
|
|
16
17
|
import colorama
|
17
18
|
import filelock
|
18
|
-
import psutil
|
19
19
|
|
20
20
|
from sky import global_user_state
|
21
21
|
from sky import sky_logging
|
22
|
+
from sky.adaptors import common as adaptors_common
|
22
23
|
from sky.skylet import constants
|
23
24
|
from sky.utils import common_utils
|
24
25
|
from sky.utils import db_utils
|
@@ -26,6 +27,11 @@ from sky.utils import log_utils
|
|
26
27
|
from sky.utils import message_utils
|
27
28
|
from sky.utils import subprocess_utils
|
28
29
|
|
30
|
+
if typing.TYPE_CHECKING:
|
31
|
+
import psutil
|
32
|
+
else:
|
33
|
+
psutil = adaptors_common.LazyImport('psutil')
|
34
|
+
|
29
35
|
logger = sky_logging.init_logger(__name__)
|
30
36
|
|
31
37
|
_LINUX_NEW_LINE = '\n'
|
sky/skypilot_config.py
CHANGED
@@ -53,18 +53,23 @@ import copy
|
|
53
53
|
import os
|
54
54
|
import pprint
|
55
55
|
import tempfile
|
56
|
+
import typing
|
56
57
|
from typing import Any, Dict, Iterator, Optional, Tuple
|
57
58
|
|
58
|
-
import yaml
|
59
|
-
|
60
59
|
from sky import exceptions
|
61
60
|
from sky import sky_logging
|
61
|
+
from sky.adaptors import common as adaptors_common
|
62
62
|
from sky.skylet import constants
|
63
63
|
from sky.utils import common_utils
|
64
64
|
from sky.utils import config_utils
|
65
65
|
from sky.utils import schemas
|
66
66
|
from sky.utils import ux_utils
|
67
67
|
|
68
|
+
if typing.TYPE_CHECKING:
|
69
|
+
import yaml
|
70
|
+
else:
|
71
|
+
yaml = adaptors_common.LazyImport('yaml')
|
72
|
+
|
68
73
|
logger = sky_logging.init_logger(__name__)
|
69
74
|
|
70
75
|
# The config path is discovered in this order:
|
sky/task.py
CHANGED
@@ -9,12 +9,12 @@ from typing import (Any, Callable, Dict, Iterable, List, Optional, Set, Tuple,
|
|
9
9
|
Union)
|
10
10
|
|
11
11
|
import colorama
|
12
|
-
import yaml
|
13
12
|
|
14
13
|
import sky
|
15
14
|
from sky import clouds
|
16
15
|
from sky import exceptions
|
17
16
|
from sky import sky_logging
|
17
|
+
from sky.adaptors import common as adaptors_common
|
18
18
|
import sky.dag
|
19
19
|
from sky.data import data_utils
|
20
20
|
from sky.data import storage as storage_lib
|
@@ -26,7 +26,11 @@ from sky.utils import schemas
|
|
26
26
|
from sky.utils import ux_utils
|
27
27
|
|
28
28
|
if typing.TYPE_CHECKING:
|
29
|
+
import yaml
|
30
|
+
|
29
31
|
from sky import resources as resources_lib
|
32
|
+
else:
|
33
|
+
yaml = adaptors_common.LazyImport('yaml')
|
30
34
|
|
31
35
|
logger = sky_logging.init_logger(__name__)
|
32
36
|
|
sky/utils/common_utils.py
CHANGED
@@ -13,22 +13,30 @@ import re
|
|
13
13
|
import socket
|
14
14
|
import sys
|
15
15
|
import time
|
16
|
+
import typing
|
16
17
|
from typing import Any, Callable, Dict, List, Optional, Union
|
17
18
|
import uuid
|
18
19
|
|
19
|
-
import jinja2
|
20
|
-
import jsonschema
|
21
|
-
import psutil
|
22
|
-
import yaml
|
23
|
-
|
24
20
|
from sky import exceptions
|
25
21
|
from sky import sky_logging
|
22
|
+
from sky.adaptors import common as adaptors_common
|
26
23
|
from sky.skylet import constants
|
27
24
|
from sky.usage import constants as usage_constants
|
28
25
|
from sky.utils import annotations
|
29
26
|
from sky.utils import ux_utils
|
30
27
|
from sky.utils import validator
|
31
28
|
|
29
|
+
if typing.TYPE_CHECKING:
|
30
|
+
import jinja2
|
31
|
+
import jsonschema
|
32
|
+
import psutil
|
33
|
+
import yaml
|
34
|
+
else:
|
35
|
+
jinja2 = adaptors_common.LazyImport('jinja2')
|
36
|
+
jsonschema = adaptors_common.LazyImport('jsonschema')
|
37
|
+
psutil = adaptors_common.LazyImport('psutil')
|
38
|
+
yaml = adaptors_common.LazyImport('yaml')
|
39
|
+
|
32
40
|
_USER_HASH_FILE = os.path.expanduser('~/.sky/user_hash')
|
33
41
|
USER_HASH_LENGTH = 8
|
34
42
|
|
@@ -598,7 +606,7 @@ def validate_schema(obj, schema, err_msg_prefix='', skip_none=True):
|
|
598
606
|
obj = {k: v for k, v in obj.items() if v is not None}
|
599
607
|
err_msg = None
|
600
608
|
try:
|
601
|
-
validator.
|
609
|
+
validator.get_schema_validator()(schema).validate(obj)
|
602
610
|
except jsonschema.ValidationError as e:
|
603
611
|
if e.validator == 'additionalProperties':
|
604
612
|
if tuple(e.schema_path) == ('properties', 'envs',
|
sky/utils/log_utils.py
CHANGED
@@ -2,20 +2,26 @@
|
|
2
2
|
import enum
|
3
3
|
import time
|
4
4
|
import types
|
5
|
+
import typing
|
5
6
|
from typing import Callable, Iterator, List, Optional, TextIO, Type
|
6
7
|
|
7
8
|
import colorama
|
8
|
-
# slow due to https://github.com/python-pendulum/pendulum/issues/808
|
9
|
-
# FIXME(aylei): bump pendulum if it get fixed
|
10
|
-
import pendulum
|
11
9
|
import prettytable
|
12
10
|
|
13
11
|
from sky import sky_logging
|
12
|
+
from sky.adaptors import common as adaptors_common
|
14
13
|
from sky.utils import rich_utils
|
15
14
|
from sky.utils import ux_utils
|
16
15
|
|
17
16
|
logger = sky_logging.init_logger(__name__)
|
18
17
|
|
18
|
+
if typing.TYPE_CHECKING:
|
19
|
+
# slow due to https://github.com/python-pendulum/pendulum/issues/808
|
20
|
+
# FIXME(aylei): bump pendulum if it get fixed
|
21
|
+
import pendulum
|
22
|
+
else:
|
23
|
+
pendulum = adaptors_common.LazyImport('pendulum')
|
24
|
+
|
19
25
|
|
20
26
|
class LineProcessor(object):
|
21
27
|
"""A processor for log lines."""
|
@@ -0,0 +1,21 @@
|
|
1
|
+
"""Utility functions for rich console."""
|
2
|
+
import typing
|
3
|
+
|
4
|
+
from sky.adaptors import common as adaptors_common
|
5
|
+
|
6
|
+
if typing.TYPE_CHECKING:
|
7
|
+
import rich.console as rich_console
|
8
|
+
else:
|
9
|
+
rich_console = adaptors_common.LazyImport('rich.console')
|
10
|
+
|
11
|
+
_console = None # Lazy initialized console
|
12
|
+
|
13
|
+
|
14
|
+
# Move global console to a function to avoid
|
15
|
+
# importing rich console if not used
|
16
|
+
def get_console():
|
17
|
+
"""Get or create the rich console."""
|
18
|
+
global _console
|
19
|
+
if _console is None:
|
20
|
+
_console = rich_console.Console(soft_wrap=True)
|
21
|
+
return _console
|
sky/utils/rich_utils.py
CHANGED
@@ -6,15 +6,18 @@ import threading
|
|
6
6
|
import typing
|
7
7
|
from typing import Dict, Iterator, Optional, Tuple, Union
|
8
8
|
|
9
|
-
|
10
|
-
|
9
|
+
from sky.adaptors import common as adaptors_common
|
11
10
|
from sky.utils import annotations
|
12
11
|
from sky.utils import message_utils
|
12
|
+
from sky.utils import rich_console_utils
|
13
13
|
|
14
14
|
if typing.TYPE_CHECKING:
|
15
15
|
import requests
|
16
|
+
import rich.console as rich_console
|
17
|
+
else:
|
18
|
+
requests = adaptors_common.LazyImport('requests')
|
19
|
+
rich_console = adaptors_common.LazyImport('rich.console')
|
16
20
|
|
17
|
-
console = rich_console.Console(soft_wrap=True)
|
18
21
|
_statuses: Dict[str, Optional[Union['EncodedStatus',
|
19
22
|
'rich_console.Status']]] = {
|
20
23
|
'server': None,
|
@@ -141,15 +144,28 @@ class _RevertibleStatus:
|
|
141
144
|
return _statuses[self.status_type]
|
142
145
|
|
143
146
|
def __exit__(self, exc_type, exc_val, exc_tb):
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
147
|
+
# We use the same lock with the `safe_logger` to avoid the following 2
|
148
|
+
# raice conditions. We refer loggers in another thread as "thread
|
149
|
+
# logger" hereafter.
|
150
|
+
# 1. When a thread logger stopped the status in `safe_logger`, and
|
151
|
+
# here we exit the status and set it to None. Then the thread logger
|
152
|
+
# will raise an error when it tries to restart the status.
|
153
|
+
# 2. When a thread logger stopped the status in `safe_logger`, and
|
154
|
+
# here we exit the status and entered a new one. Then the thread
|
155
|
+
# logger will raise an error when it tries to restart the old status,
|
156
|
+
# since only one LiveStatus can be started at the same time.
|
157
|
+
# Please refer to #4995 for more information.
|
158
|
+
with _logging_lock:
|
159
|
+
global _status_nesting_level
|
160
|
+
_status_nesting_level -= 1
|
161
|
+
if _status_nesting_level <= 0:
|
162
|
+
_status_nesting_level = 0
|
163
|
+
if _statuses[self.status_type] is not None:
|
164
|
+
_statuses[self.status_type].__exit__(
|
165
|
+
exc_type, exc_val, exc_tb)
|
166
|
+
_statuses[self.status_type] = None
|
167
|
+
else:
|
168
|
+
_statuses[self.status_type].update(self.previous_message)
|
153
169
|
|
154
170
|
def update(self, *args, **kwargs):
|
155
171
|
_statuses[self.status_type].update(*args, **kwargs)
|
@@ -219,7 +235,7 @@ def client_status(msg: str) -> Union['rich_console.Status', _NoOpConsoleStatus]:
|
|
219
235
|
if (threading.current_thread() is threading.main_thread() and
|
220
236
|
not sky_logging.is_silent()):
|
221
237
|
if _statuses['client'] is None:
|
222
|
-
_statuses['client'] =
|
238
|
+
_statuses['client'] = rich_console_utils.get_console().status(msg)
|
223
239
|
return _RevertibleStatus(msg, 'client')
|
224
240
|
return _NoOpConsoleStatus()
|
225
241
|
|
sky/utils/subprocess_utils.py
CHANGED
@@ -8,19 +8,25 @@ import shlex
|
|
8
8
|
import subprocess
|
9
9
|
import threading
|
10
10
|
import time
|
11
|
+
import typing
|
11
12
|
from typing import Any, Callable, Dict, List, Optional, Protocol, Tuple, Union
|
12
13
|
|
13
14
|
import colorama
|
14
|
-
import psutil
|
15
15
|
|
16
16
|
from sky import exceptions
|
17
17
|
from sky import sky_logging
|
18
|
+
from sky.adaptors import common as adaptors_common
|
18
19
|
from sky.skylet import constants
|
19
20
|
from sky.skylet import log_lib
|
20
21
|
from sky.utils import common_utils
|
21
22
|
from sky.utils import timeline
|
22
23
|
from sky.utils import ux_utils
|
23
24
|
|
25
|
+
if typing.TYPE_CHECKING:
|
26
|
+
import psutil
|
27
|
+
else:
|
28
|
+
psutil = adaptors_common.LazyImport('psutil')
|
29
|
+
|
24
30
|
logger = sky_logging.init_logger(__name__)
|
25
31
|
|
26
32
|
_fd_limit_warning_shown = False
|
sky/utils/ux_utils.py
CHANGED
@@ -8,17 +8,15 @@ import typing
|
|
8
8
|
from typing import Callable, Optional, Union
|
9
9
|
|
10
10
|
import colorama
|
11
|
-
import rich.console as rich_console
|
12
11
|
|
13
12
|
from sky import sky_logging
|
14
13
|
from sky.skylet import constants
|
15
14
|
from sky.utils import common_utils
|
15
|
+
from sky.utils import rich_console_utils
|
16
16
|
|
17
17
|
if typing.TYPE_CHECKING:
|
18
18
|
import pathlib
|
19
19
|
|
20
|
-
console = rich_console.Console()
|
21
|
-
|
22
20
|
INDENT_SYMBOL = f'{colorama.Style.DIM}├── {colorama.Style.RESET_ALL}'
|
23
21
|
INDENT_LAST_SYMBOL = f'{colorama.Style.DIM}└── {colorama.Style.RESET_ALL}'
|
24
22
|
|
@@ -40,7 +38,7 @@ def console_newline():
|
|
40
38
|
|
41
39
|
Useful when catching exceptions inside console.status()
|
42
40
|
"""
|
43
|
-
|
41
|
+
rich_console_utils.get_console().print()
|
44
42
|
|
45
43
|
|
46
44
|
@contextlib.contextmanager
|
sky/utils/validator.py
CHANGED
@@ -4,7 +4,14 @@ The main motivation behind extending the existing JSON Schema validator is to
|
|
4
4
|
allow for case-insensitive enum matching since this is currently not supported
|
5
5
|
by the JSON Schema specification.
|
6
6
|
"""
|
7
|
-
import
|
7
|
+
import typing
|
8
|
+
|
9
|
+
from sky.adaptors import common as adaptors_common
|
10
|
+
|
11
|
+
if typing.TYPE_CHECKING:
|
12
|
+
import jsonschema
|
13
|
+
else:
|
14
|
+
jsonschema = adaptors_common.LazyImport('jsonschema')
|
8
15
|
|
9
16
|
|
10
17
|
def case_insensitive_enum(validator, enums, instance, schema):
|
@@ -14,6 +21,9 @@ def case_insensitive_enum(validator, enums, instance, schema):
|
|
14
21
|
f'{instance!r} is not one of {enums!r}')
|
15
22
|
|
16
23
|
|
17
|
-
|
18
|
-
|
19
|
-
|
24
|
+
# Move this to a function to delay initialization
|
25
|
+
def get_schema_validator():
|
26
|
+
"""Get the schema validator class, initializing it only when needed."""
|
27
|
+
return jsonschema.validators.extend(
|
28
|
+
jsonschema.Draft7Validator,
|
29
|
+
validators={'case_insensitive_enum': case_insensitive_enum})
|