dstack 0.19.11rc1__py3-none-any.whl → 0.19.12rc1__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 dstack might be problematic. Click here for more details.
- dstack/_internal/cli/commands/offer.py +2 -0
- dstack/_internal/cli/services/configurators/run.py +1 -1
- dstack/_internal/cli/utils/updates.py +13 -1
- dstack/_internal/core/backends/aws/compute.py +21 -9
- dstack/_internal/core/backends/base/compute.py +7 -3
- dstack/_internal/core/backends/gcp/compute.py +43 -20
- dstack/_internal/core/backends/gcp/resources.py +18 -2
- dstack/_internal/core/backends/local/compute.py +4 -2
- dstack/_internal/core/models/repos/local.py +19 -13
- dstack/_internal/server/background/tasks/process_submitted_jobs.py +3 -3
- dstack/_internal/server/routers/repos.py +9 -4
- dstack/_internal/server/services/fleets.py +2 -2
- dstack/_internal/server/services/gateways/__init__.py +1 -1
- dstack/_internal/server/services/jobs/__init__.py +4 -4
- dstack/_internal/server/services/plugins.py +64 -32
- dstack/_internal/server/services/runs.py +2 -2
- dstack/_internal/server/services/volumes.py +1 -1
- dstack/_internal/server/statics/index.html +1 -1
- dstack/_internal/server/statics/{main-b4803049eac16aea9a49.js → main-5b9786c955b42bf93581.js} +5 -5
- dstack/_internal/server/statics/{main-b4803049eac16aea9a49.js.map → main-5b9786c955b42bf93581.js.map} +1 -1
- dstack/plugins/builtin/__init__.py +0 -0
- dstack/plugins/builtin/rest_plugin/__init__.py +18 -0
- dstack/plugins/builtin/rest_plugin/_models.py +48 -0
- dstack/plugins/builtin/rest_plugin/_plugin.py +127 -0
- dstack/version.py +1 -1
- {dstack-0.19.11rc1.dist-info → dstack-0.19.12rc1.dist-info}/METADATA +2 -2
- {dstack-0.19.11rc1.dist-info → dstack-0.19.12rc1.dist-info}/RECORD +30 -27
- dstack/_internal/utils/ignore.py +0 -92
- {dstack-0.19.11rc1.dist-info → dstack-0.19.12rc1.dist-info}/WHEEL +0 -0
- {dstack-0.19.11rc1.dist-info → dstack-0.19.12rc1.dist-info}/entry_points.txt +0 -0
- {dstack-0.19.11rc1.dist-info → dstack-0.19.12rc1.dist-info}/licenses/LICENSE.md +0 -0
|
File without changes
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# ruff: noqa: F401
|
|
2
|
+
from dstack.plugins.builtin.rest_plugin._models import (
|
|
3
|
+
FleetSpecRequest,
|
|
4
|
+
FleetSpecResponse,
|
|
5
|
+
GatewaySpecRequest,
|
|
6
|
+
GatewaySpecResponse,
|
|
7
|
+
RunSpecRequest,
|
|
8
|
+
RunSpecResponse,
|
|
9
|
+
SpecApplyRequest,
|
|
10
|
+
SpecApplyResponse,
|
|
11
|
+
VolumeSpecRequest,
|
|
12
|
+
VolumeSpecResponse,
|
|
13
|
+
)
|
|
14
|
+
from dstack.plugins.builtin.rest_plugin._plugin import (
|
|
15
|
+
PLUGIN_SERVICE_URI_ENV_VAR_NAME,
|
|
16
|
+
CustomApplyPolicy,
|
|
17
|
+
RESTPlugin,
|
|
18
|
+
)
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
from typing import Generic, Optional, TypeVar
|
|
2
|
+
|
|
3
|
+
from pydantic import BaseModel, Field
|
|
4
|
+
from typing_extensions import Annotated
|
|
5
|
+
|
|
6
|
+
from dstack._internal.core.models.fleets import FleetSpec
|
|
7
|
+
from dstack._internal.core.models.gateways import GatewaySpec
|
|
8
|
+
from dstack._internal.core.models.runs import RunSpec
|
|
9
|
+
from dstack._internal.core.models.volumes import VolumeSpec
|
|
10
|
+
|
|
11
|
+
SpecType = TypeVar("SpecType", RunSpec, FleetSpec, VolumeSpec, GatewaySpec)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class SpecApplyRequest(BaseModel, Generic[SpecType]):
|
|
15
|
+
user: Annotated[str, Field(description="The name of the user making the apply request")]
|
|
16
|
+
project: Annotated[str, Field(description="The name of the project the request is for")]
|
|
17
|
+
spec: Annotated[SpecType, Field(description="The spec to be applied")]
|
|
18
|
+
|
|
19
|
+
# Override dict() to remove __orig_class__ attribute and avoid "TypeError: Object of type _GenericAlias is not JSON serializable"
|
|
20
|
+
# error. This issue doesn't happen though when running the code in pytest, only when running the server.
|
|
21
|
+
def dict(self, *args, **kwargs):
|
|
22
|
+
d = super().dict(*args, **kwargs)
|
|
23
|
+
d.pop("__orig_class__", None)
|
|
24
|
+
return d
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
RunSpecRequest = SpecApplyRequest[RunSpec]
|
|
28
|
+
FleetSpecRequest = SpecApplyRequest[FleetSpec]
|
|
29
|
+
VolumeSpecRequest = SpecApplyRequest[VolumeSpec]
|
|
30
|
+
GatewaySpecRequest = SpecApplyRequest[GatewaySpec]
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class SpecApplyResponse(BaseModel, Generic[SpecType]):
|
|
34
|
+
spec: Annotated[
|
|
35
|
+
SpecType,
|
|
36
|
+
Field(
|
|
37
|
+
description="The spec to apply, original spec if error otherwise original or mutated by plugin service if approved"
|
|
38
|
+
),
|
|
39
|
+
]
|
|
40
|
+
error: Annotated[
|
|
41
|
+
Optional[str], Field(description="Error message if request is rejected", min_length=1)
|
|
42
|
+
] = None
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
RunSpecResponse = SpecApplyResponse[RunSpec]
|
|
46
|
+
FleetSpecResponse = SpecApplyResponse[FleetSpec]
|
|
47
|
+
VolumeSpecResponse = SpecApplyResponse[VolumeSpec]
|
|
48
|
+
GatewaySpecResponse = SpecApplyResponse[GatewaySpec]
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import os
|
|
3
|
+
from typing import Type
|
|
4
|
+
|
|
5
|
+
import requests
|
|
6
|
+
from pydantic import ValidationError
|
|
7
|
+
|
|
8
|
+
from dstack._internal.core.errors import ServerClientError
|
|
9
|
+
from dstack._internal.core.models.fleets import FleetSpec
|
|
10
|
+
from dstack._internal.core.models.gateways import GatewaySpec
|
|
11
|
+
from dstack._internal.core.models.volumes import VolumeSpec
|
|
12
|
+
from dstack.plugins import ApplyPolicy, ApplySpec, Plugin, RunSpec, get_plugin_logger
|
|
13
|
+
from dstack.plugins.builtin.rest_plugin import (
|
|
14
|
+
FleetSpecRequest,
|
|
15
|
+
FleetSpecResponse,
|
|
16
|
+
GatewaySpecRequest,
|
|
17
|
+
GatewaySpecResponse,
|
|
18
|
+
RunSpecRequest,
|
|
19
|
+
RunSpecResponse,
|
|
20
|
+
SpecApplyRequest,
|
|
21
|
+
SpecApplyResponse,
|
|
22
|
+
VolumeSpecRequest,
|
|
23
|
+
VolumeSpecResponse,
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
logger = get_plugin_logger(__name__)
|
|
27
|
+
|
|
28
|
+
PLUGIN_SERVICE_URI_ENV_VAR_NAME = "DSTACK_PLUGIN_SERVICE_URI"
|
|
29
|
+
PLUGIN_REQUEST_TIMEOUT_SEC = 8
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class CustomApplyPolicy(ApplyPolicy):
|
|
33
|
+
def __init__(self):
|
|
34
|
+
self._plugin_service_uri = os.getenv(PLUGIN_SERVICE_URI_ENV_VAR_NAME)
|
|
35
|
+
logger.info(f"Found plugin service at {self._plugin_service_uri}")
|
|
36
|
+
if not self._plugin_service_uri:
|
|
37
|
+
logger.error(
|
|
38
|
+
f"Cannot create policy because {PLUGIN_SERVICE_URI_ENV_VAR_NAME} is not set"
|
|
39
|
+
)
|
|
40
|
+
raise ServerClientError(f"{PLUGIN_SERVICE_URI_ENV_VAR_NAME} is not set")
|
|
41
|
+
|
|
42
|
+
def _check_request_rejected(self, response: SpecApplyResponse):
|
|
43
|
+
if response.error is not None:
|
|
44
|
+
logger.error(f"Plugin service rejected apply request: {response.error}")
|
|
45
|
+
raise ServerClientError(f"Apply request rejected: {response.error}")
|
|
46
|
+
|
|
47
|
+
def _call_plugin_service(self, spec_request: SpecApplyRequest, endpoint: str) -> ApplySpec:
|
|
48
|
+
response = None
|
|
49
|
+
try:
|
|
50
|
+
response = requests.post(
|
|
51
|
+
f"{self._plugin_service_uri}{endpoint}",
|
|
52
|
+
json=spec_request.dict(),
|
|
53
|
+
headers={"accept": "application/json", "Content-Type": "application/json"},
|
|
54
|
+
timeout=PLUGIN_REQUEST_TIMEOUT_SEC,
|
|
55
|
+
)
|
|
56
|
+
response.raise_for_status()
|
|
57
|
+
spec_json = json.loads(response.text)
|
|
58
|
+
return spec_json
|
|
59
|
+
except requests.exceptions.ConnectionError as e:
|
|
60
|
+
logger.error(
|
|
61
|
+
f"Could not connect to plugin service at {self._plugin_service_uri}: %s", e
|
|
62
|
+
)
|
|
63
|
+
raise ServerClientError(
|
|
64
|
+
f"Could not connect to plugin service at {self._plugin_service_uri}"
|
|
65
|
+
)
|
|
66
|
+
except requests.RequestException as e:
|
|
67
|
+
logger.error("Request to the plugin service failed: %s", e)
|
|
68
|
+
raise ServerClientError("Request to the plugin service failed")
|
|
69
|
+
|
|
70
|
+
def _on_apply(
|
|
71
|
+
self,
|
|
72
|
+
request_cls: Type[SpecApplyRequest],
|
|
73
|
+
response_cls: Type[SpecApplyResponse],
|
|
74
|
+
endpoint: str,
|
|
75
|
+
user: str,
|
|
76
|
+
project: str,
|
|
77
|
+
spec: ApplySpec,
|
|
78
|
+
) -> ApplySpec:
|
|
79
|
+
try:
|
|
80
|
+
spec_request = request_cls(user=user, project=project, spec=spec)
|
|
81
|
+
spec_json = self._call_plugin_service(spec_request, endpoint)
|
|
82
|
+
response = response_cls(**spec_json)
|
|
83
|
+
self._check_request_rejected(response)
|
|
84
|
+
return response.spec
|
|
85
|
+
except ValidationError:
|
|
86
|
+
logger.error(f"Plugin service returned invalid response:\n{spec_json}")
|
|
87
|
+
raise ServerClientError("Plugin service returned an invalid response")
|
|
88
|
+
|
|
89
|
+
def on_run_apply(self, user: str, project: str, spec: RunSpec) -> RunSpec:
|
|
90
|
+
return self._on_apply(
|
|
91
|
+
RunSpecRequest, RunSpecResponse, "/apply_policies/on_run_apply", user, project, spec
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
def on_fleet_apply(self, user: str, project: str, spec: FleetSpec) -> FleetSpec:
|
|
95
|
+
return self._on_apply(
|
|
96
|
+
FleetSpecRequest,
|
|
97
|
+
FleetSpecResponse,
|
|
98
|
+
"/apply_policies/on_fleet_apply",
|
|
99
|
+
user,
|
|
100
|
+
project,
|
|
101
|
+
spec,
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
def on_volume_apply(self, user: str, project: str, spec: VolumeSpec) -> VolumeSpec:
|
|
105
|
+
return self._on_apply(
|
|
106
|
+
VolumeSpecRequest,
|
|
107
|
+
VolumeSpecResponse,
|
|
108
|
+
"/apply_policies/on_volume_apply",
|
|
109
|
+
user,
|
|
110
|
+
project,
|
|
111
|
+
spec,
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
def on_gateway_apply(self, user: str, project: str, spec: GatewaySpec) -> GatewaySpec:
|
|
115
|
+
return self._on_apply(
|
|
116
|
+
GatewaySpecRequest,
|
|
117
|
+
GatewaySpecResponse,
|
|
118
|
+
"/apply_policies/on_gateway_apply",
|
|
119
|
+
user,
|
|
120
|
+
project,
|
|
121
|
+
spec,
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
class RESTPlugin(Plugin):
|
|
126
|
+
def get_apply_policies(self) -> list[ApplyPolicy]:
|
|
127
|
+
return [CustomApplyPolicy()]
|
dstack/version.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: dstack
|
|
3
|
-
Version: 0.19.
|
|
3
|
+
Version: 0.19.12rc1
|
|
4
4
|
Summary: dstack is an open-source orchestration engine for running AI workloads on any cloud or on-premises.
|
|
5
5
|
Project-URL: Homepage, https://dstack.ai
|
|
6
6
|
Project-URL: Source, https://github.com/dstackai/dstack
|
|
@@ -22,7 +22,7 @@ Requires-Dist: cursor
|
|
|
22
22
|
Requires-Dist: filelock
|
|
23
23
|
Requires-Dist: gitpython
|
|
24
24
|
Requires-Dist: gpuhunt==0.1.6
|
|
25
|
-
Requires-Dist:
|
|
25
|
+
Requires-Dist: ignore-python>=0.2.0
|
|
26
26
|
Requires-Dist: jsonschema
|
|
27
27
|
Requires-Dist: packaging
|
|
28
28
|
Requires-Dist: paramiko>=3.2.0
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
dstack/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
-
dstack/version.py,sha256=
|
|
2
|
+
dstack/version.py,sha256=hwGn7URuuYv71W9BadPvs-Et3ttZHW-XD5QkVNM2wew,68
|
|
3
3
|
dstack/_internal/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
4
|
dstack/_internal/compat.py,sha256=bF9U9fTMfL8UVhCouedoUSTYFl7UAOiU0WXrnRoByxw,40
|
|
5
5
|
dstack/_internal/settings.py,sha256=GOqfcLEONWC1hGU36IYPuOhJXP_qC3Y6d2SQge_NdpY,953
|
|
@@ -16,7 +16,7 @@ dstack/_internal/cli/commands/gateway.py,sha256=DcD6P_MvXbSL9aXkLX9hgGYSAzARjgY6
|
|
|
16
16
|
dstack/_internal/cli/commands/init.py,sha256=bLhSlViNWtjflB6xNq_PuCR2o2A06h222luh1NeUgVA,1169
|
|
17
17
|
dstack/_internal/cli/commands/logs.py,sha256=o8ehPAKM12Xn9thg2jjnYdr7_wKqF-00ziVry8IVVwE,1528
|
|
18
18
|
dstack/_internal/cli/commands/metrics.py,sha256=ZS_dHD4_YK135J09xKpVTY_3CXzhj8QhDo18Ail9Pas,5862
|
|
19
|
-
dstack/_internal/cli/commands/offer.py,sha256=
|
|
19
|
+
dstack/_internal/cli/commands/offer.py,sha256=6gem4Wz6WJmHur9-eiC65JwqObrGIAybROCAp5pr59k,4221
|
|
20
20
|
dstack/_internal/cli/commands/project.py,sha256=V8gJwQWQGvGKQJPUyce_M7Ij_B7bOxYzo2IQgkLLHFE,6151
|
|
21
21
|
dstack/_internal/cli/commands/ps.py,sha256=5RU4mcL4-FT4PcXktfKb4htCOPqia7mIuVGgfK7x9lY,1894
|
|
22
22
|
dstack/_internal/cli/commands/server.py,sha256=4K0tp_tIUStCEMpWrUkRLwe27IgAt99RPpk2H1AWnXk,2817
|
|
@@ -32,7 +32,7 @@ dstack/_internal/cli/services/configurators/__init__.py,sha256=z94VPBFqybP8Zpwy3
|
|
|
32
32
|
dstack/_internal/cli/services/configurators/base.py,sha256=bGfde2zoma28lLE8MUACO4-NKT1CdJJQJoXrzjpz0mQ,3360
|
|
33
33
|
dstack/_internal/cli/services/configurators/fleet.py,sha256=jm4tNH6QQVplLdboCTlvRYUee3nZ0UYb_qLTrvtYVYM,14049
|
|
34
34
|
dstack/_internal/cli/services/configurators/gateway.py,sha256=czB2s89s7IowOmWnpDwWErPAUlW3FvFMizImhrkQiBM,8927
|
|
35
|
-
dstack/_internal/cli/services/configurators/run.py,sha256=
|
|
35
|
+
dstack/_internal/cli/services/configurators/run.py,sha256=PvaetsuW6p5rM-nH06uIQR7xXL4GDnbr2O8Sh9r0Dcw,25534
|
|
36
36
|
dstack/_internal/cli/services/configurators/volume.py,sha256=riMXLQbgvHIIFwLKdHfad-_0iE9wE3G_rUmXU5P3ZS8,8519
|
|
37
37
|
dstack/_internal/cli/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
38
38
|
dstack/_internal/cli/utils/common.py,sha256=rfmzqrsgR3rXW3wj0vxDdvrhUUg2aIy4A6E9MZbd55g,1763
|
|
@@ -40,7 +40,7 @@ dstack/_internal/cli/utils/fleet.py,sha256=ch-LN1X9boSm-rFLW4mAJRmz0XliLhH0LvKD2
|
|
|
40
40
|
dstack/_internal/cli/utils/gateway.py,sha256=qMYa1NTAT_O98x2_mSyWDRbiHj5fqt6xUXFh9NIUwAM,1502
|
|
41
41
|
dstack/_internal/cli/utils/rich.py,sha256=Gx1MJU929kMKsbdo9qF7XHARNta2426Ssb-xMLVhwbQ,5710
|
|
42
42
|
dstack/_internal/cli/utils/run.py,sha256=nCQwAU3VDS8ec2oWNjRKi5xIGdwwKI_YNr8vgGyDPzQ,9202
|
|
43
|
-
dstack/_internal/cli/utils/updates.py,sha256=
|
|
43
|
+
dstack/_internal/cli/utils/updates.py,sha256=pGr5keEmHojnbY0ayjWL4GWTz4ParY6fP85tHpJ11pI,3043
|
|
44
44
|
dstack/_internal/cli/utils/volume.py,sha256=mU9I06dVMFbpjfkefxrZNoSWadKLoib3U14rHudNQN4,1975
|
|
45
45
|
dstack/_internal/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
46
46
|
dstack/_internal/core/consts.py,sha256=c1Yd5UY6Qx7KeuYgloXWncWhMsYj6TqwlElda7NtB98,254
|
|
@@ -51,7 +51,7 @@ dstack/_internal/core/backends/models.py,sha256=aKQOrDEStouuwY4MacSen7SkoyAa6HR6
|
|
|
51
51
|
dstack/_internal/core/backends/aws/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
52
52
|
dstack/_internal/core/backends/aws/auth.py,sha256=BAe3HAedoAO42Fbv7YhpODKWlyil8M0PuRJsL-_u_kw,978
|
|
53
53
|
dstack/_internal/core/backends/aws/backend.py,sha256=pjROH-S9pgrSMm-Eox_ocL7cTU6mIMRxvURq7Vi-2J8,876
|
|
54
|
-
dstack/_internal/core/backends/aws/compute.py,sha256=
|
|
54
|
+
dstack/_internal/core/backends/aws/compute.py,sha256=GKxwfoDA_qVE1znwRGfvkPhvrl3XUDL9tAlFidB4SYs,36040
|
|
55
55
|
dstack/_internal/core/backends/aws/configurator.py,sha256=gGynfTQW89hUt7acAjVnZnRtCbzhno7l4baCKnBEuQI,7499
|
|
56
56
|
dstack/_internal/core/backends/aws/models.py,sha256=EUCHXHmZnshe3rwI9UtjilwcUMu1Z7MO4Y4-nlZ_IcA,4404
|
|
57
57
|
dstack/_internal/core/backends/aws/resources.py,sha256=Wht_USG8ps9HQBhAYfxDxjaob9kUnr7_WDCaXNzCeE0,22837
|
|
@@ -65,7 +65,7 @@ dstack/_internal/core/backends/azure/resources.py,sha256=cJWS2Yjxdg-XtjpdBxfVDZa
|
|
|
65
65
|
dstack/_internal/core/backends/azure/utils.py,sha256=taHMJq6UHRzUXLUcO2P5VCKy3wJaye2bG-6QdkEPNdY,1741
|
|
66
66
|
dstack/_internal/core/backends/base/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
67
67
|
dstack/_internal/core/backends/base/backend.py,sha256=hdFMHED1RMV9GVfLSU0yGhGE-cXlbLvt1coDA885PMM,505
|
|
68
|
-
dstack/_internal/core/backends/base/compute.py,sha256=
|
|
68
|
+
dstack/_internal/core/backends/base/compute.py,sha256=D4rRxUHUZOkUfAhmDE6MaS4AyHEPdRVcnS4LxQ-DF9E,28719
|
|
69
69
|
dstack/_internal/core/backends/base/configurator.py,sha256=OCv8N2oxcxy3In2zS1PKiCJ0a-COZwxGjBz2FYkQnfg,3807
|
|
70
70
|
dstack/_internal/core/backends/base/models.py,sha256=Ij0osOl-T-ABsKLoVg2eY81DMkwdWkevAnjXj2QnLXI,532
|
|
71
71
|
dstack/_internal/core/backends/base/offers.py,sha256=AzAAx5eSTaHv8CbWuGERTHS151x4oJuQn3tr_Bz9HKQ,6282
|
|
@@ -85,10 +85,10 @@ dstack/_internal/core/backends/dstack/models.py,sha256=Jbe0Syez43N5i97TlIc8l-5Vn
|
|
|
85
85
|
dstack/_internal/core/backends/gcp/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
86
86
|
dstack/_internal/core/backends/gcp/auth.py,sha256=VWCn34hapaZ3E0OHCoiAVL97o3s64RF9w85CZ6xdtmk,2235
|
|
87
87
|
dstack/_internal/core/backends/gcp/backend.py,sha256=OvTv1c7j4LTPCIEtkwD3-q6Eo1QET8xlM8CzbY0hLmI,572
|
|
88
|
-
dstack/_internal/core/backends/gcp/compute.py,sha256=
|
|
88
|
+
dstack/_internal/core/backends/gcp/compute.py,sha256=OObZgsOyQC-FvcA75xdO7MIoiFr9ncl5-Av6TtCOxdQ,42218
|
|
89
89
|
dstack/_internal/core/backends/gcp/configurator.py,sha256=mvI7WMz8cC1YnN-0KFIIEqkfcEBehRJI0WgKnqILjv0,6730
|
|
90
90
|
dstack/_internal/core/backends/gcp/models.py,sha256=biLA3rlFcoPatAZpKycuIl-8PdnNSAFiDCJjov65_zo,4612
|
|
91
|
-
dstack/_internal/core/backends/gcp/resources.py,sha256=
|
|
91
|
+
dstack/_internal/core/backends/gcp/resources.py,sha256=2jpg24NH4Ov4J4Of1F3DPkwEWkRxEi-x4ZTx8XSNGIQ,16926
|
|
92
92
|
dstack/_internal/core/backends/gcp/features/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
93
93
|
dstack/_internal/core/backends/gcp/features/tcpx.py,sha256=8bDR5kwF5qke5EWNdBscdbZQnC7oVXKSls3WPcoXgZI,2902
|
|
94
94
|
dstack/_internal/core/backends/kubernetes/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -105,7 +105,7 @@ dstack/_internal/core/backends/lambdalabs/configurator.py,sha256=JYtAFemQRi6tXTt
|
|
|
105
105
|
dstack/_internal/core/backends/lambdalabs/models.py,sha256=c9dAYd0wjun2dvMLUZO4D09XvEskBRehjLDN_nwbSEU,1036
|
|
106
106
|
dstack/_internal/core/backends/local/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
107
107
|
dstack/_internal/core/backends/local/backend.py,sha256=KJuNXUXrg60NhLywnExD1EXH2gK0TL-kzNWUPRNZ_Zg,427
|
|
108
|
-
dstack/_internal/core/backends/local/compute.py,sha256
|
|
108
|
+
dstack/_internal/core/backends/local/compute.py,sha256=-FUD8Ii5VTBtygAV1U3k1j10MFdK1whGvrSeRwTk29Y,3788
|
|
109
109
|
dstack/_internal/core/backends/nebius/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
110
110
|
dstack/_internal/core/backends/nebius/backend.py,sha256=2XqZIbSR8VzlfOnuVklXlDxNmwAkQj7txQN8VXF1j2E,566
|
|
111
111
|
dstack/_internal/core/backends/nebius/compute.py,sha256=OUNvDk9rU13NR0CADFqn7nQL8kxgSvL7kbNEV4cLzyQ,14761
|
|
@@ -178,7 +178,7 @@ dstack/_internal/core/models/backends/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCe
|
|
|
178
178
|
dstack/_internal/core/models/backends/base.py,sha256=Fbhs90NBMceXhjORwj7c2_pVriapCGSUMBFwuR-wRIg,1091
|
|
179
179
|
dstack/_internal/core/models/repos/__init__.py,sha256=7Qo1QgJ852LklUuM-mlCNFodp_XrQ4iqV7uRPiX_qm0,885
|
|
180
180
|
dstack/_internal/core/models/repos/base.py,sha256=nErlSR3AbG9fwDE5vuJK5DIrP8JB3fG8a7mXqosJ9gY,846
|
|
181
|
-
dstack/_internal/core/models/repos/local.py,sha256=
|
|
181
|
+
dstack/_internal/core/models/repos/local.py,sha256=ET-b6UsncxPGeDUH97hOCr3k6j3SnL8SX34geqQDSl8,2848
|
|
182
182
|
dstack/_internal/core/models/repos/remote.py,sha256=r50v39KHhoVMfdnIHe58VJEi2Abm-37Y1ttXigdjc9o,11553
|
|
183
183
|
dstack/_internal/core/models/repos/virtual.py,sha256=8g4hGSQ6Z8oDKoF6cj2souJ2A5vRop5OyFCQ5z84rw4,2582
|
|
184
184
|
dstack/_internal/core/services/__init__.py,sha256=UVVcj26WYVgo7jHzD07sNRqSOO7zA3QzQv-9LnCDqR4,415
|
|
@@ -264,7 +264,7 @@ dstack/_internal/server/background/tasks/process_placement_groups.py,sha256=gJ8U
|
|
|
264
264
|
dstack/_internal/server/background/tasks/process_prometheus_metrics.py,sha256=9VoGFqdiXcVkCi_NV1VqQdqllDkB0bHIqOHKMIZK1Fg,5183
|
|
265
265
|
dstack/_internal/server/background/tasks/process_running_jobs.py,sha256=jyuYOQfXIVGu5ugTennwSGXL_c6VDNJN96-Qrz7Hgic,36441
|
|
266
266
|
dstack/_internal/server/background/tasks/process_runs.py,sha256=EI1W6HUyB-og3g8BDP_GsBrJjQ-Z3JvZHTuJf7CRKRM,17974
|
|
267
|
-
dstack/_internal/server/background/tasks/process_submitted_jobs.py,sha256=
|
|
267
|
+
dstack/_internal/server/background/tasks/process_submitted_jobs.py,sha256=tLLpdtLHN2xC6Ohc6f0we3oevw3pBt0_XrsufaFtIvE,27383
|
|
268
268
|
dstack/_internal/server/background/tasks/process_terminating_jobs.py,sha256=0Z3Q409RwSxOL_pgK8JktBthjtESEUH3ahwTLsTdYPk,3800
|
|
269
269
|
dstack/_internal/server/background/tasks/process_volumes.py,sha256=206rbT4ICeZtEmqh_94Rry_fgHfFLLaSEX9W-svwFk4,5089
|
|
270
270
|
dstack/_internal/server/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -347,7 +347,7 @@ dstack/_internal/server/routers/logs.py,sha256=_Euk283LbhlwHibJTKM-7YcpbeQFtWBqM
|
|
|
347
347
|
dstack/_internal/server/routers/metrics.py,sha256=VFgWhkOvxVFDLlRM_kXHYFylLcfCD6UjXInvcd7H4dY,2314
|
|
348
348
|
dstack/_internal/server/routers/projects.py,sha256=0R-w_6WXUbNo6fREAexFUQ3RoOJF2D_Iz35elKjym14,2717
|
|
349
349
|
dstack/_internal/server/routers/prometheus.py,sha256=UAcOE8dpGZe4Wd0EOIlFPMbjaNjzX8A7iHlooeRvsfo,944
|
|
350
|
-
dstack/_internal/server/routers/repos.py,sha256=
|
|
350
|
+
dstack/_internal/server/routers/repos.py,sha256=Si27qslFefmvRBuR2khvuFyjpd88-Hys-pvIbi9YJK0,3943
|
|
351
351
|
dstack/_internal/server/routers/runs.py,sha256=p44c_0bqwG1v5S_qX-HKbap1nmk1F2JVqaIXihjiUfY,5388
|
|
352
352
|
dstack/_internal/server/routers/secrets.py,sha256=50_qJCTYRpnGSlLyS93gqoV17wWewOVmM65PcG1bT_Y,856
|
|
353
353
|
dstack/_internal/server/routers/server.py,sha256=8pQmfyZj0nbebeOK9JuKhw9JmYuIYfJnY0LuYynWnGY,346
|
|
@@ -372,7 +372,7 @@ dstack/_internal/server/security/permissions.py,sha256=FJ_8YPhjmebA4jQjtQoAGEaj1
|
|
|
372
372
|
dstack/_internal/server/services/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
373
373
|
dstack/_internal/server/services/config.py,sha256=yo8njslwfS7_blhbPPhOtzCMyg8N_mmFSw5aPvirSzw,10691
|
|
374
374
|
dstack/_internal/server/services/docker.py,sha256=zAvjFHxIP03Td92NzbGEScz0piLjloE60tQ7vz0AeCA,5328
|
|
375
|
-
dstack/_internal/server/services/fleets.py,sha256=
|
|
375
|
+
dstack/_internal/server/services/fleets.py,sha256=9UL9mHo0IJhYrxiFHQUaLUA61PAQQ8gGwYNHpknlVqU,26599
|
|
376
376
|
dstack/_internal/server/services/instances.py,sha256=4feu9RfixOIVsLoFPHiYYUe0L6sf3v3h1asTBSF5cyc,18686
|
|
377
377
|
dstack/_internal/server/services/locking.py,sha256=7JUgNSplKRx7dxC4LIpmWw81agUtslEDTeDiNMPbAVg,3013
|
|
378
378
|
dstack/_internal/server/services/logging.py,sha256=Nu1628kW2hqB__N0Eyr07wGWjVWxfyJnczonTJ72kSM,417
|
|
@@ -380,15 +380,15 @@ dstack/_internal/server/services/metrics.py,sha256=jKLy1jSCVR_crqVu_CmsOMbvMkucW
|
|
|
380
380
|
dstack/_internal/server/services/offers.py,sha256=4hhqLzmo14_IY84FSDG59Sib1DrmTAOk-_q8M4aYoLU,7737
|
|
381
381
|
dstack/_internal/server/services/permissions.py,sha256=l7Ngdelmn65vjw13NcOdaC6lBYMRuSw6FbHzYwdK3nE,1005
|
|
382
382
|
dstack/_internal/server/services/placement.py,sha256=U-7z4kJ6ZyrCXzkDychWoOhniz19ooFwiNI2InoTLls,2420
|
|
383
|
-
dstack/_internal/server/services/plugins.py,sha256=
|
|
383
|
+
dstack/_internal/server/services/plugins.py,sha256=KgBqBUqxjQirRcYNuXVetE4OQj0EPkdC7ccbrNV1WQE,3825
|
|
384
384
|
dstack/_internal/server/services/projects.py,sha256=Je1iWZ-ArmyFxK1yMUzod5WRXyiIDxtuVp6pHcdctTQ,14988
|
|
385
385
|
dstack/_internal/server/services/prometheus.py,sha256=xq5G-Q2BJup9lS2F6__0wUVTs-k1Gr3dYclGzo2WoWo,12474
|
|
386
386
|
dstack/_internal/server/services/repos.py,sha256=f9ztN7jz_2gvD9hXF5sJwWDVyG2-NHRfjIdSukowPh8,9342
|
|
387
387
|
dstack/_internal/server/services/resources.py,sha256=VRFOih_cMJdc0c2m9nSGsX8vWAJQV3M6N87aqS_JXfw,699
|
|
388
|
-
dstack/_internal/server/services/runs.py,sha256=
|
|
388
|
+
dstack/_internal/server/services/runs.py,sha256=7nj4iQ6CZT3SEW9h3Vb8CBV65MUSSeQfZwgP_J4YlMo,39179
|
|
389
389
|
dstack/_internal/server/services/storage.py,sha256=6I0xI_3_RpJNbKZwHjDnjrEwXGdHfiaeb5li15T-M1I,1884
|
|
390
390
|
dstack/_internal/server/services/users.py,sha256=W-5xL7zsHNjeG7BBK54RWGvIrBOrw-FF0NcG_z9qhoE,7466
|
|
391
|
-
dstack/_internal/server/services/volumes.py,sha256=
|
|
391
|
+
dstack/_internal/server/services/volumes.py,sha256=vxjFn3ijrvwi9-aXipT0iQgNjgebdwcBRn1mKFL9zAQ,16244
|
|
392
392
|
dstack/_internal/server/services/backends/__init__.py,sha256=Aqo1GoqhZ_FsLEkCcBrvReKSq6E5w4QbBLrDXfGjiKU,13154
|
|
393
393
|
dstack/_internal/server/services/backends/handlers.py,sha256=j-MhBxrpdepoDG7f2tApjFnE23RVO5I15-hxHyOWnew,3251
|
|
394
394
|
dstack/_internal/server/services/encryption/__init__.py,sha256=3kCw_cxC3-Un1OIofdW5Gqsm0ZCXXTlGz09cULBx_uc,3155
|
|
@@ -396,11 +396,11 @@ dstack/_internal/server/services/encryption/keys/__init__.py,sha256=47DEQpj8HBSa
|
|
|
396
396
|
dstack/_internal/server/services/encryption/keys/aes.py,sha256=2He1p2_Rg6hnCeLIGJo-Yfdsij7so_338oY49RXuL3Q,2276
|
|
397
397
|
dstack/_internal/server/services/encryption/keys/base.py,sha256=mqumJiidoexUPoqxhQG6J_SpC1WGYwkdjKm1MUWnXo8,352
|
|
398
398
|
dstack/_internal/server/services/encryption/keys/identity.py,sha256=ryb_YSV6u4c7W1OsVfEpzJvZCrR4zZYlzLw_GpjpD2Q,741
|
|
399
|
-
dstack/_internal/server/services/gateways/__init__.py,sha256=
|
|
399
|
+
dstack/_internal/server/services/gateways/__init__.py,sha256=aDTpr45rkaQ2zBHnDQycwEDSQSno7bQ0buRPqTEDRxg,21536
|
|
400
400
|
dstack/_internal/server/services/gateways/client.py,sha256=XIJX3fGBbZ_AG8qZMTSE8KAB_ojq5YJFa0OXoD_dofg,7493
|
|
401
401
|
dstack/_internal/server/services/gateways/connection.py,sha256=ot3lV85XdmCT45vBWeyj57nLPcLPNm316zu3jMyeWjA,5625
|
|
402
402
|
dstack/_internal/server/services/gateways/pool.py,sha256=0LclTl1tyx-doS78LeaAKjr-SMp98zuwh5f9s06JSd0,1914
|
|
403
|
-
dstack/_internal/server/services/jobs/__init__.py,sha256=
|
|
403
|
+
dstack/_internal/server/services/jobs/__init__.py,sha256=hoQsjkUWdJ8xsO03WRwKOX-sHJuhVfsX-1rl26nQwR0,25554
|
|
404
404
|
dstack/_internal/server/services/jobs/configurators/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
405
405
|
dstack/_internal/server/services/jobs/configurators/base.py,sha256=WLRIBM50P8mfvpotzYjK3Gtf5ScQsuijGieH_zaYqCg,11984
|
|
406
406
|
dstack/_internal/server/services/jobs/configurators/dev.py,sha256=ufN6Sd8TwIsjQYNZE32fkAqJI7o2zjgoZThbrP-bd7U,2378
|
|
@@ -454,10 +454,10 @@ dstack/_internal/server/statics/e467d7d60aae81ab198b.svg,sha256=_XHc9mfQZgGkcy4h
|
|
|
454
454
|
dstack/_internal/server/statics/eb9b344b73818fe2b71a.png,sha256=2H14eOCQRyZhFGJ1Kn2LH1j70kTF1Qop4vH-tiKqyPI,85
|
|
455
455
|
dstack/_internal/server/statics/f517dd626eb964120de0.png,sha256=4QQuNa8SqmcZ67HK6739OHCyjnAJseU1bkcn454KRQs,159
|
|
456
456
|
dstack/_internal/server/statics/f958aecddee5d8e3222c.png,sha256=8CoZkVNgRfOAe62X1dU-AZDvwh_nESKaQblEmaX2Xrs,87
|
|
457
|
-
dstack/_internal/server/statics/index.html,sha256=
|
|
457
|
+
dstack/_internal/server/statics/index.html,sha256=WcJyCA-G5vPq0xyJH8UcyEdw-df77u9C_3S0EdfxvT8,10468
|
|
458
|
+
dstack/_internal/server/statics/main-5b9786c955b42bf93581.js,sha256=zhAnUUbO4YDnSGFJ77XNOIraIcw19ov7gokS2DLhy9E,6523313
|
|
459
|
+
dstack/_internal/server/statics/main-5b9786c955b42bf93581.js.map,sha256=6SX5ZigfpMVtB3xLBJb4IME1ifg1IwqsyMy8NKTSiq8,8561465
|
|
458
460
|
dstack/_internal/server/statics/main-8f9c66f404e9c7e7e020.css,sha256=RC2sAxRMpIK3myvsxKEhLk4OsxTOt7DgWunCwyn-B34,1336694
|
|
459
|
-
dstack/_internal/server/statics/main-b4803049eac16aea9a49.js,sha256=uk2mEKXEKDP5nWO6cjSGK0GUh63YbvSBCgHCiengeKk,6521276
|
|
460
|
-
dstack/_internal/server/statics/main-b4803049eac16aea9a49.js.map,sha256=tDM8-Gh0SsJV87gQICQKhrvprc5eb33M4OCpLGa982c,8559017
|
|
461
461
|
dstack/_internal/server/statics/manifest.json,sha256=430w2BoWVmYYVr14lDvUxx-ROPt3VjigzeMqfLeiSCM,340
|
|
462
462
|
dstack/_internal/server/statics/robots.txt,sha256=kNJLw79pisHhc3OVAimMzKcq3x9WT6sF9IS4xI0crdI,67
|
|
463
463
|
dstack/_internal/server/statics/assets/android-chrome-144x144.png,sha256=tB3V-95O-VVEoawN5V1XFoMQRSK0I6gthraV8bATGaw,23414
|
|
@@ -549,7 +549,6 @@ dstack/_internal/utils/env.py,sha256=HRbIspHpKHh05fMZeV23-hrZoV6vVMuniefD08u6ey0
|
|
|
549
549
|
dstack/_internal/utils/event_loop.py,sha256=DO2ADtWfH2z8F2hBbg_EADSWzleQYGVZ9D1XYDpH-tk,880
|
|
550
550
|
dstack/_internal/utils/gpu.py,sha256=ZeWpy1nRLVh-FwBZdxbMoVjjCF0DWJlWfNoVgFhGx2w,1776
|
|
551
551
|
dstack/_internal/utils/hash.py,sha256=mCERRtj9QwbpoP3vveBqbniSJiNMHG0vPSzp4fxmKv0,920
|
|
552
|
-
dstack/_internal/utils/ignore.py,sha256=Lb5l_qTxOApHGPRu_YHkpTB9e5P0KIOFibMm8vTs_eQ,3138
|
|
553
552
|
dstack/_internal/utils/interpolator.py,sha256=kLRm_DagGcjnkLPtMC9NaHioegsUvg8uk4lom38eV3I,2922
|
|
554
553
|
dstack/_internal/utils/json_schema.py,sha256=oh23z6jdl_wx3qkojk_2egyKZbdmYWZs12Gd9Bk46M8,371
|
|
555
554
|
dstack/_internal/utils/logging.py,sha256=j37rgL-fQh2_E3ec_RqDy6Ora-Aa79ZVV-BAgZJViME,97
|
|
@@ -584,8 +583,12 @@ dstack/plugins/__init__.py,sha256=buT1pcyORLgVbl89ATkRWJPhvejriVz7sNBjvuZRCRE,40
|
|
|
584
583
|
dstack/plugins/_base.py,sha256=-etiB-EozaJCg2wtmONfj8ic-K03qXvXyl_TIDp-kNE,2662
|
|
585
584
|
dstack/plugins/_models.py,sha256=1Gw--mDQ1_0FFr9Zur9LE8UbMoWESUpTdHHt12AyIZo,341
|
|
586
585
|
dstack/plugins/_utils.py,sha256=FqeWYb7zOrgZkO9Bd8caL5I81_TUEsysIzvxsULrmzk,392
|
|
587
|
-
dstack
|
|
588
|
-
dstack
|
|
589
|
-
dstack
|
|
590
|
-
dstack
|
|
591
|
-
dstack-0.19.
|
|
586
|
+
dstack/plugins/builtin/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
587
|
+
dstack/plugins/builtin/rest_plugin/__init__.py,sha256=lgTsq8Z6Km2F2UhPRChVB4vDM5ZpWtdk1iB1aa20ypA,440
|
|
588
|
+
dstack/plugins/builtin/rest_plugin/_models.py,sha256=9hgVuU6OGSxidar88XhQnNo9izYWeQvVH45ciErv-Es,1910
|
|
589
|
+
dstack/plugins/builtin/rest_plugin/_plugin.py,sha256=LbtjnXqd-51pR19Cr5rYxoIyDKjSOG4hIpXmv1Mpfnc,4615
|
|
590
|
+
dstack-0.19.12rc1.dist-info/METADATA,sha256=ysn5aUHpxpI_UTqDNLjGErkH2getUqLN3YMfpcVqs6s,20516
|
|
591
|
+
dstack-0.19.12rc1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
592
|
+
dstack-0.19.12rc1.dist-info/entry_points.txt,sha256=GnLrMS8hx3rWAySQjA7tPNhtixV6a-brRkmal1PKoHc,58
|
|
593
|
+
dstack-0.19.12rc1.dist-info/licenses/LICENSE.md,sha256=qDABaRGjSKVOib1U8viw2P_96sIK7Puo426784oD9f8,15976
|
|
594
|
+
dstack-0.19.12rc1.dist-info/RECORD,,
|
dstack/_internal/utils/ignore.py
DELETED
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
import fnmatch
|
|
2
|
-
from itertools import zip_longest
|
|
3
|
-
from pathlib import Path
|
|
4
|
-
from typing import Dict, List, Optional
|
|
5
|
-
|
|
6
|
-
from dstack._internal.utils.path import PathLike
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
class GitIgnore:
|
|
10
|
-
def __init__(
|
|
11
|
-
self, root_dir: PathLike, ignore_files: List[str] = None, globs: List[str] = None
|
|
12
|
-
):
|
|
13
|
-
self.root_dir = Path(root_dir)
|
|
14
|
-
self.ignore_files = (
|
|
15
|
-
ignore_files
|
|
16
|
-
if ignore_files is not None
|
|
17
|
-
else [".gitignore", ".git/info/exclude", ".dstackignore"]
|
|
18
|
-
)
|
|
19
|
-
self.ignore_globs: Dict[str, List[str]] = {".": globs or []}
|
|
20
|
-
self.load_recursive()
|
|
21
|
-
|
|
22
|
-
def load_ignore_file(self, path: str, ignore_file: Path):
|
|
23
|
-
if path != "." and not path.startswith("./"):
|
|
24
|
-
path = "./" + path
|
|
25
|
-
if path not in self.ignore_globs:
|
|
26
|
-
self.ignore_globs[path] = []
|
|
27
|
-
with ignore_file.open("r") as f:
|
|
28
|
-
for line in f:
|
|
29
|
-
line = self.rstrip(line.rstrip("\n")).rstrip("/")
|
|
30
|
-
line = line.replace("\\ ", " ")
|
|
31
|
-
if line.startswith("#") or not line:
|
|
32
|
-
continue
|
|
33
|
-
self.ignore_globs[path].append(line)
|
|
34
|
-
|
|
35
|
-
def load_recursive(self, path: Optional[Path] = None):
|
|
36
|
-
path = path or self.root_dir
|
|
37
|
-
for ignore_file in self.ignore_files:
|
|
38
|
-
ignore_file = path / ignore_file
|
|
39
|
-
if ignore_file.exists():
|
|
40
|
-
self.load_ignore_file(str(path.relative_to(self.root_dir)), ignore_file)
|
|
41
|
-
|
|
42
|
-
for subdir in path.iterdir():
|
|
43
|
-
if not subdir.is_dir() or self.ignore(subdir.relative_to(self.root_dir)):
|
|
44
|
-
continue
|
|
45
|
-
self.load_recursive(subdir)
|
|
46
|
-
|
|
47
|
-
@staticmethod
|
|
48
|
-
def rstrip(value: str) -> str:
|
|
49
|
-
end = len(value) - 1
|
|
50
|
-
while end >= 0:
|
|
51
|
-
if not value[end].isspace():
|
|
52
|
-
break
|
|
53
|
-
if end > 0 and value[end - 1] == "\\":
|
|
54
|
-
break # escaped space
|
|
55
|
-
end -= 1
|
|
56
|
-
else:
|
|
57
|
-
return ""
|
|
58
|
-
return value[: end + 1]
|
|
59
|
-
|
|
60
|
-
@staticmethod
|
|
61
|
-
def fnmatch(name: str, pattern: str, sep="/") -> bool:
|
|
62
|
-
if pattern.startswith(sep):
|
|
63
|
-
name = sep + name
|
|
64
|
-
for n, p in zip_longest(
|
|
65
|
-
reversed(name.split(sep)), reversed(pattern.split(sep)), fillvalue=None
|
|
66
|
-
):
|
|
67
|
-
if p == "**":
|
|
68
|
-
raise NotImplementedError()
|
|
69
|
-
if p is None:
|
|
70
|
-
return True
|
|
71
|
-
if n is None or not fnmatch.fnmatch(n, p):
|
|
72
|
-
return False
|
|
73
|
-
return True
|
|
74
|
-
|
|
75
|
-
def ignore(self, path: PathLike, sep="/") -> bool:
|
|
76
|
-
if not path:
|
|
77
|
-
return False
|
|
78
|
-
path = Path(path)
|
|
79
|
-
if path.is_absolute():
|
|
80
|
-
path = path.relative_to(self.root_dir)
|
|
81
|
-
|
|
82
|
-
tokens = ("." + sep + str(path)).split(sep)
|
|
83
|
-
for i in range(1, len(tokens)):
|
|
84
|
-
parent = sep.join(tokens[:-i])
|
|
85
|
-
globs = self.ignore_globs.get(parent)
|
|
86
|
-
if not globs:
|
|
87
|
-
continue
|
|
88
|
-
name = sep.join(tokens[-i:])
|
|
89
|
-
for glob in globs:
|
|
90
|
-
if self.fnmatch(name, glob, sep=sep):
|
|
91
|
-
return True
|
|
92
|
-
return False
|
|
File without changes
|
|
File without changes
|
|
File without changes
|