truefoundry 0.11.11rc1__py3-none-any.whl → 0.12.0__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 truefoundry might be problematic. Click here for more details.
- truefoundry/common/storage_provider_utils.py +35 -10
- truefoundry/common/utils.py +4 -0
- truefoundry/deploy/_autogen/models.py +7 -7
- truefoundry/deploy/builder/builders/dockerfile.py +4 -6
- truefoundry/deploy/builder/builders/tfy_python_buildpack/dockerfile_template.py +8 -4
- truefoundry/deploy/builder/builders/tfy_spark_buildpack/dockerfile_template.py +1 -7
- truefoundry/deploy/builder/builders/tfy_task_pyspark_buildpack/dockerfile_template.py +1 -11
- truefoundry/deploy/builder/utils.py +13 -0
- truefoundry/deploy/lib/util.py +102 -17
- truefoundry/deploy/v2/lib/deploy.py +4 -0
- truefoundry/deploy/v2/lib/patched_models.py +6 -30
- truefoundry/deploy/v2/lib/source.py +6 -35
- truefoundry/ml/artifact/truefoundry_artifact_repo.py +25 -11
- truefoundry/ml/log_types/artifacts/artifact.py +3 -2
- truefoundry/ml/log_types/artifacts/model.py +1 -0
- {truefoundry-0.11.11rc1.dist-info → truefoundry-0.12.0.dist-info}/METADATA +1 -1
- {truefoundry-0.11.11rc1.dist-info → truefoundry-0.12.0.dist-info}/RECORD +19 -19
- {truefoundry-0.11.11rc1.dist-info → truefoundry-0.12.0.dist-info}/WHEEL +0 -0
- {truefoundry-0.11.11rc1.dist-info → truefoundry-0.12.0.dist-info}/entry_points.txt +0 -0
|
@@ -22,6 +22,23 @@ from truefoundry.pydantic_v1 import BaseModel
|
|
|
22
22
|
logger = logging.getLogger("truefoundry")
|
|
23
23
|
|
|
24
24
|
|
|
25
|
+
def truncate_path_for_progress(
|
|
26
|
+
path: str, max_length: int, relpath: bool = False
|
|
27
|
+
) -> str:
|
|
28
|
+
if relpath:
|
|
29
|
+
path = os.path.relpath(path)
|
|
30
|
+
if len(path) <= max_length:
|
|
31
|
+
return path
|
|
32
|
+
parts = path.split(os.sep)
|
|
33
|
+
result = parts[-1] # start with filename
|
|
34
|
+
i = len(parts) - 2
|
|
35
|
+
# keep prepending directories until adding more would exceed max_len - 3
|
|
36
|
+
while i >= 0 and len(result) + len(parts[i]) + 1 <= max_length - 3:
|
|
37
|
+
result = parts[i] + os.sep + result
|
|
38
|
+
i -= 1
|
|
39
|
+
return "..." + os.sep + result
|
|
40
|
+
|
|
41
|
+
|
|
25
42
|
class MultiPartUploadStorageProvider(str, Enum):
|
|
26
43
|
S3_COMPATIBLE = "S3_COMPATIBLE"
|
|
27
44
|
AZURE_BLOB = "AZURE_BLOB"
|
|
@@ -182,7 +199,7 @@ def _file_part_upload(
|
|
|
182
199
|
return response
|
|
183
200
|
|
|
184
201
|
|
|
185
|
-
def s3_compatible_multipart_upload(
|
|
202
|
+
def s3_compatible_multipart_upload( # noqa: C901
|
|
186
203
|
multipart_upload: MultiPartUpload,
|
|
187
204
|
local_file: str,
|
|
188
205
|
multipart_info: _FileMultiPartInfo,
|
|
@@ -190,13 +207,15 @@ def s3_compatible_multipart_upload(
|
|
|
190
207
|
progress_bar: Optional[Progress] = None,
|
|
191
208
|
abort_event: Optional[Event] = None,
|
|
192
209
|
exception_class=HttpRequestException,
|
|
193
|
-
):
|
|
210
|
+
) -> None:
|
|
194
211
|
abort_event = abort_event or Event()
|
|
195
212
|
parts = []
|
|
196
213
|
|
|
197
|
-
if progress_bar:
|
|
214
|
+
if progress_bar is not None:
|
|
198
215
|
multi_part_upload_progress = progress_bar.add_task(
|
|
199
|
-
f"[green]
|
|
216
|
+
f"[green]⬆ {truncate_path_for_progress(local_file, 64, relpath=True)}",
|
|
217
|
+
start=True,
|
|
218
|
+
visible=True,
|
|
200
219
|
)
|
|
201
220
|
|
|
202
221
|
def upload(part_number: int, seek: int) -> None:
|
|
@@ -221,7 +240,7 @@ def s3_compatible_multipart_upload(
|
|
|
221
240
|
multipart_info.num_parts,
|
|
222
241
|
local_file,
|
|
223
242
|
)
|
|
224
|
-
if progress_bar:
|
|
243
|
+
if progress_bar is not None:
|
|
225
244
|
progress_bar.update(
|
|
226
245
|
multi_part_upload_progress,
|
|
227
246
|
advance=multipart_info.part_size,
|
|
@@ -254,10 +273,12 @@ def s3_compatible_multipart_upload(
|
|
|
254
273
|
timeout=2 * 60,
|
|
255
274
|
)
|
|
256
275
|
response.raise_for_status()
|
|
276
|
+
if progress_bar is not None:
|
|
277
|
+
progress_bar.refresh()
|
|
257
278
|
logger.debug("Multipart upload of %s completed", local_file)
|
|
258
279
|
|
|
259
280
|
|
|
260
|
-
def azure_multi_part_upload(
|
|
281
|
+
def azure_multi_part_upload( # noqa: C901
|
|
261
282
|
multipart_upload: MultiPartUpload,
|
|
262
283
|
local_file: str,
|
|
263
284
|
multipart_info: _FileMultiPartInfo,
|
|
@@ -265,12 +286,14 @@ def azure_multi_part_upload(
|
|
|
265
286
|
progress_bar: Optional[Progress] = None,
|
|
266
287
|
abort_event: Optional[Event] = None,
|
|
267
288
|
exception_class=HttpRequestException,
|
|
268
|
-
):
|
|
289
|
+
) -> None:
|
|
269
290
|
abort_event = abort_event or Event()
|
|
270
291
|
|
|
271
|
-
if progress_bar:
|
|
292
|
+
if progress_bar is not None:
|
|
272
293
|
multi_part_upload_progress = progress_bar.add_task(
|
|
273
|
-
f"[green]
|
|
294
|
+
f"[green]⬆ {truncate_path_for_progress(local_file, 64, relpath=True)}",
|
|
295
|
+
start=True,
|
|
296
|
+
visible=True,
|
|
274
297
|
)
|
|
275
298
|
|
|
276
299
|
def upload(part_number: int, seek: int):
|
|
@@ -289,7 +312,7 @@ def azure_multi_part_upload(
|
|
|
289
312
|
abort_event=abort_event,
|
|
290
313
|
exception_class=exception_class,
|
|
291
314
|
)
|
|
292
|
-
if progress_bar:
|
|
315
|
+
if progress_bar is not None:
|
|
293
316
|
progress_bar.update(
|
|
294
317
|
multi_part_upload_progress,
|
|
295
318
|
advance=multipart_info.part_size,
|
|
@@ -328,4 +351,6 @@ def azure_multi_part_upload(
|
|
|
328
351
|
timeout=2 * 60,
|
|
329
352
|
)
|
|
330
353
|
response.raise_for_status()
|
|
354
|
+
if progress_bar is not None:
|
|
355
|
+
progress_bar.refresh()
|
|
331
356
|
logger.debug("Multipart upload of %s completed", local_file)
|
truefoundry/common/utils.py
CHANGED
|
@@ -210,3 +210,7 @@ def get_user_agent() -> str:
|
|
|
210
210
|
return f"truefoundry/{__version__} Python/{platform.python_version()} OS/{platform.system()}-{platform.release()} ({platform.architecture()[0]})"
|
|
211
211
|
except Exception:
|
|
212
212
|
return f"truefoundry/{__version__}"
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
def get_expanded_and_absolute_path(path: str):
|
|
216
|
+
return os.path.abspath(os.path.expanduser(path))
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# generated by datamodel-codegen:
|
|
2
2
|
# filename: application.json
|
|
3
|
-
# timestamp: 2025-09-
|
|
3
|
+
# timestamp: 2025-09-10T19:32:14+00:00
|
|
4
4
|
|
|
5
5
|
from __future__ import annotations
|
|
6
6
|
|
|
@@ -621,8 +621,8 @@ class Pip(BaseModel):
|
|
|
621
621
|
|
|
622
622
|
class Poetry(BaseModel):
|
|
623
623
|
"""
|
|
624
|
-
Use `poetry` to setup
|
|
625
|
-
Your build context root must contain
|
|
624
|
+
Use `poetry` to setup env
|
|
625
|
+
Your build context root must contain `pyproject.toml` and `poetry.lock
|
|
626
626
|
"""
|
|
627
627
|
|
|
628
628
|
type: Literal["poetry"] = Field(..., description="")
|
|
@@ -1060,7 +1060,7 @@ class TaskPythonBuild(BaseModel):
|
|
|
1060
1060
|
)
|
|
1061
1061
|
cuda_version: Optional[
|
|
1062
1062
|
constr(
|
|
1063
|
-
regex=r"^((\d+\.\d+(\.\d+)?-cudnn\d+-(runtime|devel)-ubuntu\d+\.\d+)|11\.0-cudnn8|11\.1-cudnn8|11\.2-cudnn8|11\.3-cudnn8|11\.4-cudnn8|11\.5-cudnn8|11\.6-cudnn8|11\.7-cudnn8|11\.8-cudnn8|12\.0-cudnn8|12\.1-cudnn8|12\.2-cudnn8|12\.3-cudnn9|12\.4-cudnn9|12\.5-cudnn9|12\.6-cudnn9)$"
|
|
1063
|
+
regex=r"^((\d+\.\d+(\.\d+)?-cudnn\d+-(runtime|devel)-ubuntu\d+\.\d+)|11\.0-cudnn8|11\.1-cudnn8|11\.2-cudnn8|11\.3-cudnn8|11\.4-cudnn8|11\.5-cudnn8|11\.6-cudnn8|11\.7-cudnn8|11\.8-cudnn8|12\.0-cudnn8|12\.1-cudnn8|12\.2-cudnn8|12\.3-cudnn9|12\.4-cudnn9|12\.5-cudnn9|12\.6-cudnn9|12\.8-cudnn9|12\.9-cudnn9)$"
|
|
1064
1064
|
)
|
|
1065
1065
|
] = Field(
|
|
1066
1066
|
None,
|
|
@@ -1094,8 +1094,8 @@ class TrueFoundryInteractiveLogin(BaseModel):
|
|
|
1094
1094
|
|
|
1095
1095
|
class UV(BaseModel):
|
|
1096
1096
|
"""
|
|
1097
|
-
Use `uv` to setup
|
|
1098
|
-
Your build context root must contain
|
|
1097
|
+
Use `uv` to setup env.
|
|
1098
|
+
Your build context root must contain `pyproject.toml` and `uv.lock
|
|
1099
1099
|
"""
|
|
1100
1100
|
|
|
1101
1101
|
type: Literal["uv"] = Field(..., description="")
|
|
@@ -1448,7 +1448,7 @@ class PythonBuild(BaseModel):
|
|
|
1448
1448
|
)
|
|
1449
1449
|
cuda_version: Optional[
|
|
1450
1450
|
constr(
|
|
1451
|
-
regex=r"^((\d+\.\d+(\.\d+)?-cudnn\d+-(runtime|devel)-ubuntu\d+\.\d+)|11\.0-cudnn8|11\.1-cudnn8|11\.2-cudnn8|11\.3-cudnn8|11\.4-cudnn8|11\.5-cudnn8|11\.6-cudnn8|11\.7-cudnn8|11\.8-cudnn8|12\.0-cudnn8|12\.1-cudnn8|12\.2-cudnn8|12\.3-cudnn9|12\.4-cudnn9|12\.5-cudnn9|12\.6-cudnn9)$"
|
|
1451
|
+
regex=r"^((\d+\.\d+(\.\d+)?-cudnn\d+-(runtime|devel)-ubuntu\d+\.\d+)|11\.0-cudnn8|11\.1-cudnn8|11\.2-cudnn8|11\.3-cudnn8|11\.4-cudnn8|11\.5-cudnn8|11\.6-cudnn8|11\.7-cudnn8|11\.8-cudnn8|12\.0-cudnn8|12\.1-cudnn8|12\.2-cudnn8|12\.3-cudnn9|12\.4-cudnn9|12\.5-cudnn9|12\.6-cudnn9|12\.8-cudnn9|12\.9-cudnn9)$"
|
|
1452
1452
|
)
|
|
1453
1453
|
] = Field(
|
|
1454
1454
|
None,
|
|
@@ -14,22 +14,20 @@ def _get_expanded_and_absolute_path(path: str):
|
|
|
14
14
|
|
|
15
15
|
def _build_docker_image(
|
|
16
16
|
tag: str,
|
|
17
|
+
dockerfile: str,
|
|
17
18
|
path: str = ".",
|
|
18
|
-
file: Optional[str] = None,
|
|
19
19
|
build_args: Optional[Dict[str, str]] = None,
|
|
20
20
|
extra_opts: Optional[List[str]] = None,
|
|
21
21
|
):
|
|
22
|
+
dockerfile = _get_expanded_and_absolute_path(dockerfile)
|
|
22
23
|
path = _get_expanded_and_absolute_path(path)
|
|
23
24
|
|
|
24
|
-
if file:
|
|
25
|
-
file = _get_expanded_and_absolute_path(file)
|
|
26
|
-
|
|
27
25
|
build_docker_image(
|
|
28
26
|
path=path,
|
|
29
27
|
tag=tag,
|
|
30
28
|
# TODO: can we pick target platform(s) picked from cluster
|
|
31
29
|
platform="linux/amd64",
|
|
32
|
-
dockerfile=
|
|
30
|
+
dockerfile=dockerfile,
|
|
33
31
|
build_args=build_args,
|
|
34
32
|
extra_opts=extra_opts,
|
|
35
33
|
)
|
|
@@ -50,8 +48,8 @@ def build(
|
|
|
50
48
|
|
|
51
49
|
_build_docker_image(
|
|
52
50
|
tag=tag,
|
|
51
|
+
dockerfile=build_configuration.dockerfile_path,
|
|
53
52
|
path=build_configuration.build_context_path,
|
|
54
|
-
file=build_configuration.dockerfile_path,
|
|
55
53
|
build_args=build_configuration.build_args,
|
|
56
54
|
extra_opts=extra_opts,
|
|
57
55
|
)
|
|
@@ -6,6 +6,7 @@ from jinja2 import Template
|
|
|
6
6
|
from truefoundry.common.constants import ENV_VARS, PythonPackageManager
|
|
7
7
|
from truefoundry.deploy._autogen.models import UV, Pip, Poetry
|
|
8
8
|
from truefoundry.deploy.builder.utils import (
|
|
9
|
+
check_whether_poetry_toml_exists,
|
|
9
10
|
generate_apt_install_command,
|
|
10
11
|
generate_command_to_install_from_uv_lock,
|
|
11
12
|
generate_pip_install_command,
|
|
@@ -18,7 +19,6 @@ from truefoundry.deploy.v2.lib.patched_models import (
|
|
|
18
19
|
CUDAVersion,
|
|
19
20
|
PythonBuild,
|
|
20
21
|
_resolve_requirements_path,
|
|
21
|
-
check_whether_poetry_toml_exists,
|
|
22
22
|
)
|
|
23
23
|
from truefoundry.pydantic_v1 import BaseModel
|
|
24
24
|
|
|
@@ -224,6 +224,10 @@ def _build_template_context(
|
|
|
224
224
|
package_manager: str,
|
|
225
225
|
available_secrets: Set[str],
|
|
226
226
|
) -> TemplateContext:
|
|
227
|
+
if not build_configuration.python_version:
|
|
228
|
+
raise ValueError(
|
|
229
|
+
"`python_version` is required for `tfy-python-buildpack` builder"
|
|
230
|
+
)
|
|
227
231
|
# Set up package manager config secret mount
|
|
228
232
|
python_dependencies_type = python_dependencies.type
|
|
229
233
|
package_manager_config_secret_mount = ""
|
|
@@ -235,7 +239,7 @@ def _build_template_context(
|
|
|
235
239
|
)
|
|
236
240
|
|
|
237
241
|
# Configure dependencies based on type
|
|
238
|
-
if
|
|
242
|
+
if isinstance(python_dependencies, UV):
|
|
239
243
|
uv_context = _build_uv_context(
|
|
240
244
|
python_dependencies,
|
|
241
245
|
available_secrets,
|
|
@@ -252,7 +256,7 @@ def _build_template_context(
|
|
|
252
256
|
],
|
|
253
257
|
final_uv_sync_command=uv_context["final_uv_sync_command"],
|
|
254
258
|
)
|
|
255
|
-
elif
|
|
259
|
+
elif isinstance(python_dependencies, Poetry):
|
|
256
260
|
poetry_toml_exists = check_whether_poetry_toml_exists(
|
|
257
261
|
build_context_path=build_configuration.build_context_path,
|
|
258
262
|
)
|
|
@@ -271,7 +275,7 @@ def _build_template_context(
|
|
|
271
275
|
poetry_version_expression=poetry_context["poetry_version_expression"],
|
|
272
276
|
poetry_toml_exists=poetry_toml_exists,
|
|
273
277
|
)
|
|
274
|
-
elif
|
|
278
|
+
elif isinstance(python_dependencies, Pip):
|
|
275
279
|
pip_context = _build_pip_context(
|
|
276
280
|
build_configuration,
|
|
277
281
|
python_dependencies,
|
|
@@ -10,9 +10,6 @@ from truefoundry.deploy.builder.utils import (
|
|
|
10
10
|
generate_uv_pip_install_command,
|
|
11
11
|
get_available_secrets,
|
|
12
12
|
)
|
|
13
|
-
from truefoundry.deploy.v2.lib.patched_models import (
|
|
14
|
-
_resolve_requirements_path,
|
|
15
|
-
)
|
|
16
13
|
|
|
17
14
|
# TODO (chiragjn): Switch to a non-root user inside the container
|
|
18
15
|
|
|
@@ -79,10 +76,7 @@ def generate_dockerfile_content(
|
|
|
79
76
|
available_secrets = get_available_secrets(docker_build_extra_args)
|
|
80
77
|
|
|
81
78
|
# TODO (chiragjn): Handle recursive references to other requirements files e.g. `-r requirements-gpu.txt`
|
|
82
|
-
requirements_path =
|
|
83
|
-
build_context_path=build_configuration.build_context_path,
|
|
84
|
-
requirements_path=build_configuration.requirements_path,
|
|
85
|
-
)
|
|
79
|
+
requirements_path = build_configuration.requirements_path
|
|
86
80
|
requirements_destination_path = (
|
|
87
81
|
"/tmp/requirements.txt" if requirements_path else None
|
|
88
82
|
)
|
|
@@ -11,9 +11,6 @@ from truefoundry.deploy.builder.utils import (
|
|
|
11
11
|
generate_uv_pip_install_command,
|
|
12
12
|
get_available_secrets,
|
|
13
13
|
)
|
|
14
|
-
from truefoundry.deploy.v2.lib.patched_models import (
|
|
15
|
-
_resolve_requirements_path,
|
|
16
|
-
)
|
|
17
14
|
|
|
18
15
|
# TODO[GW]: Switch to a non-root user inside the container
|
|
19
16
|
_POST_PYTHON_INSTALL_TEMPLATE = """
|
|
@@ -65,17 +62,10 @@ def generate_dockerfile_content(
|
|
|
65
62
|
available_secrets = get_available_secrets(docker_build_extra_args)
|
|
66
63
|
|
|
67
64
|
# TODO (chiragjn): Handle recursive references to other requirements files e.g. `-r requirements-gpu.txt`
|
|
68
|
-
requirements_path =
|
|
69
|
-
build_context_path="",
|
|
70
|
-
requirements_path=build_configuration.requirements_path,
|
|
71
|
-
)
|
|
65
|
+
requirements_path = build_configuration.requirements_path
|
|
72
66
|
requirements_destination_path = (
|
|
73
67
|
"/tmp/requirements.txt" if requirements_path else None
|
|
74
68
|
)
|
|
75
|
-
# if not build_configuration.python_version:
|
|
76
|
-
# raise ValueError(
|
|
77
|
-
# "`python_version` is required for `tfy-python-buildpack` builder"
|
|
78
|
-
# )
|
|
79
69
|
pip_packages = get_additional_pip_packages(build_configuration) + (
|
|
80
70
|
build_configuration.pip_packages or []
|
|
81
71
|
)
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import os
|
|
1
2
|
import shlex
|
|
2
3
|
from typing import List, Optional, Set
|
|
3
4
|
|
|
@@ -307,3 +308,15 @@ def generate_poetry_install_command(
|
|
|
307
308
|
)
|
|
308
309
|
|
|
309
310
|
return poetry_install_cmd
|
|
311
|
+
|
|
312
|
+
|
|
313
|
+
def check_whether_poetry_toml_exists(
|
|
314
|
+
build_context_path: str,
|
|
315
|
+
) -> bool:
|
|
316
|
+
required_filename = "poetry.toml"
|
|
317
|
+
possible_path = os.path.join(build_context_path, required_filename)
|
|
318
|
+
|
|
319
|
+
if os.path.isfile(possible_path):
|
|
320
|
+
return True
|
|
321
|
+
|
|
322
|
+
return False
|
truefoundry/deploy/lib/util.py
CHANGED
|
@@ -2,7 +2,13 @@ import os
|
|
|
2
2
|
import re
|
|
3
3
|
from typing import Union
|
|
4
4
|
|
|
5
|
+
from truefoundry.common.utils import get_expanded_and_absolute_path
|
|
5
6
|
from truefoundry.deploy._autogen.models import (
|
|
7
|
+
UV,
|
|
8
|
+
Build,
|
|
9
|
+
DockerFileBuild,
|
|
10
|
+
Pip,
|
|
11
|
+
Poetry,
|
|
6
12
|
PythonBuild,
|
|
7
13
|
)
|
|
8
14
|
|
|
@@ -36,31 +42,110 @@ def find_list_paths(data, parent_key="", sep="."):
|
|
|
36
42
|
return list_paths
|
|
37
43
|
|
|
38
44
|
|
|
39
|
-
def _validate_file_path(
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
45
|
+
def _validate_file_path(
|
|
46
|
+
parent_path: str, relative_file_path: str, parent_dir_type: str
|
|
47
|
+
):
|
|
48
|
+
parent_abs = get_expanded_and_absolute_path(parent_path)
|
|
49
|
+
file_path_abs = get_expanded_and_absolute_path(
|
|
50
|
+
os.path.join(parent_abs, relative_file_path)
|
|
51
|
+
)
|
|
52
|
+
# Ensure the file path is actually inside the build context
|
|
53
|
+
outside_context = False
|
|
54
|
+
try:
|
|
55
|
+
# Use os.path.commonpath to check if file_path is inside build_context_abs
|
|
56
|
+
common_path = os.path.commonpath([parent_abs, file_path_abs])
|
|
57
|
+
outside_context = common_path != parent_abs
|
|
58
|
+
except ValueError:
|
|
59
|
+
# os.path.commonpath raises ValueError if paths are on different drives (Windows)
|
|
60
|
+
outside_context = True
|
|
61
|
+
|
|
62
|
+
if outside_context:
|
|
63
|
+
raise ValueError(
|
|
64
|
+
f"Referenced file `{relative_file_path}` is outside the {parent_dir_type} `{parent_abs}`. "
|
|
65
|
+
f"It must exist in {parent_dir_type} `{parent_abs}`."
|
|
44
66
|
)
|
|
45
67
|
|
|
68
|
+
if not os.path.exists(file_path_abs):
|
|
69
|
+
raise ValueError(
|
|
70
|
+
f"Referenced file `{relative_file_path}` not found. It must exist in {parent_dir_type} `{parent_abs}`."
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def validate_dockerfile_build_paths(
|
|
75
|
+
dockerfile_build: DockerFileBuild, project_root_path: str
|
|
76
|
+
):
|
|
77
|
+
_validate_file_path(
|
|
78
|
+
parent_path=project_root_path,
|
|
79
|
+
relative_file_path=dockerfile_build.dockerfile_path,
|
|
80
|
+
parent_dir_type="project root",
|
|
81
|
+
)
|
|
82
|
+
|
|
46
83
|
|
|
47
|
-
def
|
|
84
|
+
def validate_python_build_paths(python_build: PythonBuild, build_context_path: str):
|
|
48
85
|
if not python_build.python_dependencies:
|
|
86
|
+
# Old style flat requirements file
|
|
87
|
+
if python_build.requirements_path:
|
|
88
|
+
_validate_file_path(
|
|
89
|
+
parent_path=build_context_path,
|
|
90
|
+
relative_file_path=python_build.requirements_path,
|
|
91
|
+
parent_dir_type="build context",
|
|
92
|
+
)
|
|
49
93
|
return
|
|
50
94
|
|
|
51
|
-
if not os.path.exists(source_dir):
|
|
52
|
-
raise ValueError(f"project root path {source_dir!r} of does not exist")
|
|
53
95
|
if (
|
|
54
|
-
python_build.python_dependencies
|
|
96
|
+
isinstance(python_build.python_dependencies, Pip)
|
|
55
97
|
and python_build.python_dependencies.requirements_path
|
|
56
98
|
):
|
|
57
99
|
_validate_file_path(
|
|
58
|
-
|
|
59
|
-
python_build.python_dependencies.requirements_path,
|
|
100
|
+
parent_path=build_context_path,
|
|
101
|
+
relative_file_path=python_build.python_dependencies.requirements_path,
|
|
102
|
+
parent_dir_type="build context",
|
|
103
|
+
)
|
|
104
|
+
elif isinstance(python_build.python_dependencies, UV):
|
|
105
|
+
_validate_file_path(
|
|
106
|
+
parent_path=build_context_path,
|
|
107
|
+
relative_file_path="pyproject.toml",
|
|
108
|
+
parent_dir_type="build context",
|
|
109
|
+
)
|
|
110
|
+
_validate_file_path(
|
|
111
|
+
parent_path=build_context_path,
|
|
112
|
+
relative_file_path="uv.lock",
|
|
113
|
+
parent_dir_type="build context",
|
|
114
|
+
)
|
|
115
|
+
elif isinstance(python_build.python_dependencies, Poetry):
|
|
116
|
+
_validate_file_path(
|
|
117
|
+
parent_path=build_context_path,
|
|
118
|
+
relative_file_path="pyproject.toml",
|
|
119
|
+
parent_dir_type="build context",
|
|
120
|
+
)
|
|
121
|
+
_validate_file_path(
|
|
122
|
+
parent_path=build_context_path,
|
|
123
|
+
relative_file_path="poetry.lock",
|
|
124
|
+
parent_dir_type="build context",
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def validate_local_source_paths(component_name: str, build: Build):
|
|
129
|
+
source_dir = get_expanded_and_absolute_path(build.build_source.project_root_path)
|
|
130
|
+
if not os.path.exists(source_dir):
|
|
131
|
+
raise ValueError(
|
|
132
|
+
f"Project root path {source_dir!r} of component {component_name!r} does not exist"
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
build_context_path = get_expanded_and_absolute_path(
|
|
136
|
+
os.path.join(source_dir, build.build_spec.build_context_path)
|
|
137
|
+
)
|
|
138
|
+
if not os.path.exists(build_context_path):
|
|
139
|
+
raise ValueError(
|
|
140
|
+
f"Build context path {build_context_path!r} "
|
|
141
|
+
f"of component {component_name!r} does not exist"
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
if isinstance(build.build_spec, DockerFileBuild):
|
|
145
|
+
validate_dockerfile_build_paths(
|
|
146
|
+
dockerfile_build=build.build_spec, project_root_path=source_dir
|
|
147
|
+
)
|
|
148
|
+
elif isinstance(build.build_spec, PythonBuild):
|
|
149
|
+
validate_python_build_paths(
|
|
150
|
+
python_build=build.build_spec, build_context_path=build_context_path
|
|
60
151
|
)
|
|
61
|
-
if python_build.python_dependencies.type == "uv":
|
|
62
|
-
_validate_file_path(source_dir, "uv.lock")
|
|
63
|
-
_validate_file_path(source_dir, "pyproject.toml")
|
|
64
|
-
if python_build.python_dependencies.type == "poetry":
|
|
65
|
-
_validate_file_path(source_dir, "pyproject.toml")
|
|
66
|
-
_validate_file_path(source_dir, "poetry.lock")
|
|
@@ -15,6 +15,7 @@ from truefoundry.deploy.lib.dao.workspace import get_workspace_by_fqn
|
|
|
15
15
|
from truefoundry.deploy.lib.model.entity import Deployment, DeploymentTransitionStatus
|
|
16
16
|
from truefoundry.deploy.lib.util import (
|
|
17
17
|
get_application_fqn_from_deployment_fqn,
|
|
18
|
+
validate_local_source_paths,
|
|
18
19
|
)
|
|
19
20
|
from truefoundry.deploy.v2.lib.models import BuildResponse
|
|
20
21
|
from truefoundry.deploy.v2.lib.source import (
|
|
@@ -47,6 +48,9 @@ def _handle_if_local_source(component: Component, workspace_fqn: str) -> Compone
|
|
|
47
48
|
and isinstance(component.image.build_source, autogen_models.LocalSource)
|
|
48
49
|
):
|
|
49
50
|
new_component = component.copy(deep=True)
|
|
51
|
+
validate_local_source_paths(
|
|
52
|
+
component_name=new_component.name, build=new_component.image
|
|
53
|
+
)
|
|
50
54
|
|
|
51
55
|
if new_component.image.build_source.local_build:
|
|
52
56
|
if not env_has_docker():
|
|
@@ -47,8 +47,9 @@ or set it to None if you don't want to use any requirements file.
|
|
|
47
47
|
"""
|
|
48
48
|
|
|
49
49
|
SPECS_UPGRADE_WARNING_MESSAGE_TEMPLATE = """\
|
|
50
|
-
The `requirements_path` and `pip_packages` fields are deprecated
|
|
51
|
-
|
|
50
|
+
The `requirements_path` and `pip_packages` fields are deprecated.
|
|
51
|
+
It is recommended to use the `python_dependencies` field instead which supports pip, uv and poetry.
|
|
52
|
+
Please use the following format:
|
|
52
53
|
|
|
53
54
|
```python
|
|
54
55
|
build=Build(
|
|
@@ -106,18 +107,6 @@ def _resolve_requirements_path(
|
|
|
106
107
|
return None
|
|
107
108
|
|
|
108
109
|
|
|
109
|
-
def check_whether_poetry_toml_exists(
|
|
110
|
-
build_context_path: str,
|
|
111
|
-
) -> bool:
|
|
112
|
-
required_filename = "poetry.toml"
|
|
113
|
-
possible_path = os.path.join(build_context_path, required_filename)
|
|
114
|
-
|
|
115
|
-
if os.path.isfile(possible_path):
|
|
116
|
-
return True
|
|
117
|
-
|
|
118
|
-
return False
|
|
119
|
-
|
|
120
|
-
|
|
121
110
|
class CUDAVersion(str, enum.Enum):
|
|
122
111
|
CUDA_11_0_CUDNN8 = "11.0-cudnn8"
|
|
123
112
|
CUDA_11_1_CUDNN8 = "11.1-cudnn8"
|
|
@@ -210,7 +199,9 @@ class PythonBuild(models.PythonBuild, PatchedModelBase):
|
|
|
210
199
|
requirements_path=values.get("requirements_path"),
|
|
211
200
|
)
|
|
212
201
|
|
|
213
|
-
if
|
|
202
|
+
if (
|
|
203
|
+
values.get("requirements_path") or values.get("pip_packages")
|
|
204
|
+
) and not values.get("python_dependencies"):
|
|
214
205
|
warnings.warn(
|
|
215
206
|
SPECS_UPGRADE_WARNING_MESSAGE_TEMPLATE.format(
|
|
216
207
|
requirements_txt_path=values.get("requirements_path"),
|
|
@@ -219,27 +210,12 @@ class PythonBuild(models.PythonBuild, PatchedModelBase):
|
|
|
219
210
|
category=TrueFoundryDeprecationWarning,
|
|
220
211
|
stacklevel=2,
|
|
221
212
|
)
|
|
222
|
-
values["python_dependencies"] = Pip(
|
|
223
|
-
type="pip",
|
|
224
|
-
requirements_path=values.get("requirements_path"),
|
|
225
|
-
pip_packages=values.get("pip_packages"),
|
|
226
|
-
)
|
|
227
|
-
values.pop("pip_packages", None)
|
|
228
|
-
values.pop("requirements_path", None)
|
|
229
213
|
return values
|
|
230
214
|
|
|
231
215
|
|
|
232
216
|
class SparkBuild(models.SparkBuild, PatchedModelBase):
|
|
233
217
|
type: Literal["tfy-spark-buildpack"] = "tfy-spark-buildpack"
|
|
234
218
|
|
|
235
|
-
@root_validator
|
|
236
|
-
def validate_values(cls, values):
|
|
237
|
-
_resolve_requirements_path(
|
|
238
|
-
build_context_path=values.get("build_context_path") or "./",
|
|
239
|
-
requirements_path=values.get("requirements_path"),
|
|
240
|
-
)
|
|
241
|
-
return values
|
|
242
|
-
|
|
243
219
|
|
|
244
220
|
class SparkImageBuild(models.SparkImageBuild, PatchedModelBase):
|
|
245
221
|
type: Literal["spark-image-build"] = "spark-image-build"
|
|
@@ -9,6 +9,7 @@ import gitignorefile
|
|
|
9
9
|
from tqdm import tqdm
|
|
10
10
|
|
|
11
11
|
from truefoundry.common.types import UploadCodePackageCallable
|
|
12
|
+
from truefoundry.common.utils import get_expanded_and_absolute_path
|
|
12
13
|
from truefoundry.common.warnings import TrueFoundryDeprecationWarning
|
|
13
14
|
from truefoundry.deploy import builder
|
|
14
15
|
from truefoundry.deploy._autogen import models
|
|
@@ -21,7 +22,6 @@ from truefoundry.deploy.lib.clients.servicefoundry_client import (
|
|
|
21
22
|
ServiceFoundryServiceClient,
|
|
22
23
|
)
|
|
23
24
|
from truefoundry.deploy.lib.dao import workspace as workspace_lib
|
|
24
|
-
from truefoundry.deploy.lib.util import validate_paths
|
|
25
25
|
from truefoundry.deploy.v2.lib.patched_models import Image, RemoteSource
|
|
26
26
|
from truefoundry.logger import logger
|
|
27
27
|
|
|
@@ -142,15 +142,8 @@ def local_source_to_remote_source(
|
|
|
142
142
|
) -> RemoteSource:
|
|
143
143
|
with tempfile.TemporaryDirectory() as local_dir:
|
|
144
144
|
package_local_path = os.path.join(local_dir, "build.tar.gz")
|
|
145
|
-
source_dir =
|
|
146
|
-
|
|
147
|
-
if not os.path.exists(source_dir):
|
|
148
|
-
raise ValueError(
|
|
149
|
-
f"project root path {source_dir!r} of component {component_name!r} does not exist"
|
|
150
|
-
)
|
|
151
|
-
|
|
145
|
+
source_dir = get_expanded_and_absolute_path(local_source.project_root_path)
|
|
152
146
|
logger.info("Archiving contents of dir: %r", source_dir)
|
|
153
|
-
|
|
154
147
|
is_path_ignored = _get_callback_handler_to_ignore_file_path(source_dir)
|
|
155
148
|
_make_tarfile(
|
|
156
149
|
output_filename=package_local_path,
|
|
@@ -183,36 +176,14 @@ def local_source_to_image(
|
|
|
183
176
|
component_name: str,
|
|
184
177
|
) -> Image:
|
|
185
178
|
build = build.copy(deep=True)
|
|
186
|
-
source_dir =
|
|
187
|
-
os.path.expanduser(build.build_source.project_root_path)
|
|
188
|
-
)
|
|
189
|
-
if not os.path.exists(source_dir):
|
|
190
|
-
raise ValueError(
|
|
191
|
-
f"project root path {source_dir!r} of component {component_name!r} does not exist"
|
|
192
|
-
)
|
|
193
|
-
|
|
194
|
-
build.build_spec.build_context_path = os.path.join(
|
|
195
|
-
source_dir, build.build_spec.build_context_path
|
|
196
|
-
)
|
|
197
|
-
if not os.path.exists(build.build_spec.build_context_path):
|
|
198
|
-
raise ValueError(
|
|
199
|
-
f"Build context path {build.build_spec.build_context_path!r} "
|
|
200
|
-
f"of component {component_name!r} does not exist"
|
|
201
|
-
)
|
|
202
|
-
|
|
179
|
+
source_dir = get_expanded_and_absolute_path(build.build_source.project_root_path)
|
|
203
180
|
if isinstance(build.build_spec, models.DockerFileBuild):
|
|
204
181
|
build.build_spec.dockerfile_path = os.path.join(
|
|
205
182
|
source_dir, build.build_spec.dockerfile_path
|
|
206
183
|
)
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
f"of component {component_name!r} does not exist"
|
|
211
|
-
)
|
|
212
|
-
|
|
213
|
-
if isinstance(build.build_spec, models.PythonBuild):
|
|
214
|
-
validate_paths(build.build_spec, source_dir)
|
|
215
|
-
|
|
184
|
+
build.build_spec.build_context_path = os.path.join(
|
|
185
|
+
source_dir, build.build_spec.build_context_path
|
|
186
|
+
)
|
|
216
187
|
client = ServiceFoundryServiceClient()
|
|
217
188
|
|
|
218
189
|
workspace = workspace_lib.get_workspace_by_fqn(workspace_fqn=workspace_fqn)
|
|
@@ -40,6 +40,7 @@ from truefoundry.common.storage_provider_utils import (
|
|
|
40
40
|
azure_multi_part_upload,
|
|
41
41
|
decide_file_parts,
|
|
42
42
|
s3_compatible_multipart_upload,
|
|
43
|
+
truncate_path_for_progress,
|
|
43
44
|
)
|
|
44
45
|
from truefoundry.ml._autogen.client import ( # type: ignore[attr-defined]
|
|
45
46
|
ApiClient,
|
|
@@ -125,14 +126,14 @@ def _signed_url_upload_file(
|
|
|
125
126
|
augmented_raise_for_status(response, exception_class=MlFoundryException) # type: ignore
|
|
126
127
|
return
|
|
127
128
|
|
|
128
|
-
|
|
129
|
-
f"[green]
|
|
129
|
+
task_id = progress_bar.add_task(
|
|
130
|
+
f"[green]⬆ {truncate_path_for_progress(local_file, 64, relpath=True)}",
|
|
131
|
+
start=True,
|
|
132
|
+
visible=True,
|
|
130
133
|
)
|
|
131
134
|
|
|
132
135
|
def callback(length):
|
|
133
|
-
progress_bar.update(
|
|
134
|
-
task_progress_bar, advance=length, total=os.stat(local_file).st_size
|
|
135
|
-
)
|
|
136
|
+
progress_bar.update(task_id, advance=length, total=os.stat(local_file).st_size)
|
|
136
137
|
if abort_event and abort_event.is_set():
|
|
137
138
|
raise Exception("aborting upload")
|
|
138
139
|
|
|
@@ -147,6 +148,9 @@ def _signed_url_upload_file(
|
|
|
147
148
|
) as response:
|
|
148
149
|
augmented_raise_for_status(response, exception_class=MlFoundryException) # type: ignore
|
|
149
150
|
|
|
151
|
+
if progress_bar is not None:
|
|
152
|
+
progress_bar.refresh()
|
|
153
|
+
|
|
150
154
|
|
|
151
155
|
def _download_file_using_http_uri(
|
|
152
156
|
http_uri,
|
|
@@ -167,7 +171,11 @@ def _download_file_using_http_uri(
|
|
|
167
171
|
exception_class=MlFoundryException, # type: ignore
|
|
168
172
|
) as response:
|
|
169
173
|
augmented_raise_for_status(response, exception_class=MlFoundryException) # type: ignore
|
|
170
|
-
file_size = int(response.headers.get("Content-Length",
|
|
174
|
+
file_size = int(response.headers.get("Content-Length", -1))
|
|
175
|
+
if file_size == 0 and callback:
|
|
176
|
+
# special case for empty files
|
|
177
|
+
callback(1, 1)
|
|
178
|
+
file_size = file_size if file_size > 0 else 0
|
|
171
179
|
with open(download_path, "wb") as output_file:
|
|
172
180
|
for chunk in response.iter_content(chunk_size=chunk_size):
|
|
173
181
|
if callback:
|
|
@@ -658,15 +666,18 @@ class MlFoundryArtifactsRepository:
|
|
|
658
666
|
logger.info("Downloading %s to %s", remote_file_path, local_path)
|
|
659
667
|
|
|
660
668
|
if progress_bar is not None:
|
|
661
|
-
|
|
662
|
-
f"[green]
|
|
669
|
+
task_id = progress_bar.add_task(
|
|
670
|
+
f"[green]⬇ {truncate_path_for_progress(remote_file_path, 64)}",
|
|
671
|
+
start=True,
|
|
672
|
+
visible=True,
|
|
663
673
|
)
|
|
664
674
|
|
|
665
|
-
def callback(
|
|
675
|
+
def callback(chunk_size: int, total_file_size: int):
|
|
676
|
+
nonlocal task_id
|
|
666
677
|
if progress_bar is not None:
|
|
667
678
|
progress_bar.update(
|
|
668
|
-
|
|
669
|
-
advance=
|
|
679
|
+
task_id,
|
|
680
|
+
advance=chunk_size,
|
|
670
681
|
total=total_file_size,
|
|
671
682
|
)
|
|
672
683
|
if abort_event and abort_event.is_set():
|
|
@@ -677,6 +688,9 @@ class MlFoundryArtifactsRepository:
|
|
|
677
688
|
download_path=local_path,
|
|
678
689
|
callback=callback,
|
|
679
690
|
)
|
|
691
|
+
|
|
692
|
+
if progress_bar is not None:
|
|
693
|
+
progress_bar.refresh()
|
|
680
694
|
logger.debug("Downloaded %s to %s", remote_file_path, local_path)
|
|
681
695
|
|
|
682
696
|
def _download_artifact(
|
|
@@ -347,10 +347,11 @@ class ArtifactVersion:
|
|
|
347
347
|
artifact_version.download(path="<your-desired-download-path>")
|
|
348
348
|
```
|
|
349
349
|
"""
|
|
350
|
-
|
|
350
|
+
download_info = self._download(
|
|
351
351
|
path=path, overwrite=overwrite, progress=progress
|
|
352
352
|
)
|
|
353
|
-
|
|
353
|
+
logger.info("Downloaded artifact contents to %s", download_info.download_dir)
|
|
354
|
+
return download_info.download_dir
|
|
354
355
|
|
|
355
356
|
def delete(self) -> bool:
|
|
356
357
|
"""
|
|
@@ -48,28 +48,28 @@ truefoundry/common/exceptions.py,sha256=jkU0N7hV_P-EhXeud4I5vuB9glXXZSWPf8LcH04m
|
|
|
48
48
|
truefoundry/common/request_utils.py,sha256=e9qrAQ1MutU7JALDKcucmNd0KQEVBqgW3yx0w1zeHIU,5700
|
|
49
49
|
truefoundry/common/servicefoundry_client.py,sha256=2fYhdVPSvLXz5C5tosOq86JD8WM3IRUIy1VO9deDxZI,3340
|
|
50
50
|
truefoundry/common/session.py,sha256=d9l3TEBpqVP4mr4mTGY1qVxc815skzMlNNdw14otg34,2923
|
|
51
|
-
truefoundry/common/storage_provider_utils.py,sha256=
|
|
51
|
+
truefoundry/common/storage_provider_utils.py,sha256=jX9maCtWusZx63324cmPxHiGeIluZZzbDaJ1QYTIhAw,11856
|
|
52
52
|
truefoundry/common/types.py,sha256=BMJFCsR1lPJAw66IQBSvLyV4I6o_x5oj78gVsUa9si8,188
|
|
53
|
-
truefoundry/common/utils.py,sha256=
|
|
53
|
+
truefoundry/common/utils.py,sha256=SMpinsdXuAkIUXe7gBB8v-dWe1x2_VHdXTkA0btksDc,6816
|
|
54
54
|
truefoundry/common/warnings.py,sha256=xDMhR_-ZGC40Ycaj6nlFb5MYPexn8WbKCHd4FlflTXQ,705
|
|
55
55
|
truefoundry/deploy/__init__.py,sha256=g_g5_XKCZZXL3v_ycQhvn01bkMHweNqhOy1rg6vc5-k,2903
|
|
56
56
|
truefoundry/deploy/python_deploy_codegen.py,sha256=WwP6bIzFoLpF7J2Bgef2HMSIeefJ8TWtSv4hXNycEzQ,8872
|
|
57
|
-
truefoundry/deploy/_autogen/models.py,sha256=
|
|
57
|
+
truefoundry/deploy/_autogen/models.py,sha256=FwhfLrqrjFWY8Mzny2hlL2ksqDfVUMFFJsPb99nJ1Mc,78183
|
|
58
58
|
truefoundry/deploy/builder/__init__.py,sha256=7MEezQzxjrWpbvnONyGMqYNVVonlb8WkARob4dHzAB4,5045
|
|
59
59
|
truefoundry/deploy/builder/constants.py,sha256=aWC94kL8I8Lty9ccJwBVncsNx4ADTgPxyBxk_zur6XM,980
|
|
60
60
|
truefoundry/deploy/builder/docker_service.py,sha256=sm7GWeIqyrKaZpxskdLejZlsxcZnM3BTDJr6orvPN4E,3948
|
|
61
|
-
truefoundry/deploy/builder/utils.py,sha256=
|
|
61
|
+
truefoundry/deploy/builder/utils.py,sha256=YJVwSfzwc5OF6rDd_Gf-R1J0llARTvQ2CsauQrGP7_I,10465
|
|
62
62
|
truefoundry/deploy/builder/builders/__init__.py,sha256=Gp9NODR1E7mUjadhzIe3zzO43bBfHPeNcEDryYF2uo0,807
|
|
63
|
-
truefoundry/deploy/builder/builders/dockerfile.py,sha256=
|
|
63
|
+
truefoundry/deploy/builder/builders/dockerfile.py,sha256=PoEyWBm5NmBDIL0pAzPPt2IWXbAQTVOZ-psT5ZXxQdI,1517
|
|
64
64
|
truefoundry/deploy/builder/builders/tfy_notebook_buildpack/__init__.py,sha256=RGWGqY8xOF7vycUPJd10N7ZzahWv24lO0anrOPtLuDU,1796
|
|
65
65
|
truefoundry/deploy/builder/builders/tfy_notebook_buildpack/dockerfile_template.py,sha256=rQgdvKmAT9HArVW4TAG5yd2QTKRs3S5LJ9RQbc_EkHE,2518
|
|
66
66
|
truefoundry/deploy/builder/builders/tfy_python_buildpack/__init__.py,sha256=CGBZvmLoYLgFI98-1ulXJU-tt90OcDFJaV4dFw-aThE,1763
|
|
67
|
-
truefoundry/deploy/builder/builders/tfy_python_buildpack/dockerfile_template.py,sha256=
|
|
67
|
+
truefoundry/deploy/builder/builders/tfy_python_buildpack/dockerfile_template.py,sha256=MGLxzrOeOr6WycqssMugmh4e44f870hP7LpRoGOT9aQ,16448
|
|
68
68
|
truefoundry/deploy/builder/builders/tfy_spark_buildpack/__init__.py,sha256=4d-1lZrR70QN2fTsAaphWNRwXGx5IG99yFs6gEp7TFE,2625
|
|
69
|
-
truefoundry/deploy/builder/builders/tfy_spark_buildpack/dockerfile_template.py,sha256=
|
|
69
|
+
truefoundry/deploy/builder/builders/tfy_spark_buildpack/dockerfile_template.py,sha256=m9NMv8tDQvYQs8v5wB9hCHdJRM7L2ct3OOcAg5l0JfQ,4193
|
|
70
70
|
truefoundry/deploy/builder/builders/tfy_spark_buildpack/tfy_execute_notebook.py,sha256=-D37Zjy2SBt3RHxonPEpR1_LR0W7vTSM1kQ1S-fdK-I,6363
|
|
71
71
|
truefoundry/deploy/builder/builders/tfy_task_pyspark_buildpack/__init__.py,sha256=9LkPTAydx8UVOfKfEqfe5t7vgnc2GuNiUafCv5jcUVw,1556
|
|
72
|
-
truefoundry/deploy/builder/builders/tfy_task_pyspark_buildpack/dockerfile_template.py,sha256=
|
|
72
|
+
truefoundry/deploy/builder/builders/tfy_task_pyspark_buildpack/dockerfile_template.py,sha256=3W8_lMIVgQFc8p9btU4wOAduiOUXB-hnnbqAQ7K5Eks,4044
|
|
73
73
|
truefoundry/deploy/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
74
74
|
truefoundry/deploy/cli/commands/__init__.py,sha256=qv818jxqSAygJ3h-6Ul8t-5VOgR_UrSgsVtNCl3e5G0,1408
|
|
75
75
|
truefoundry/deploy/cli/commands/apply_command.py,sha256=DmXmKVokkauyKIiJDtErTwbJ5_LvQeJbTQsG5BjyKpo,2427
|
|
@@ -101,7 +101,7 @@ truefoundry/deploy/lib/diff_utils.py,sha256=J1sAf5O4rHNHS_MOkcB0CyaeQFtU_ALI-wd-
|
|
|
101
101
|
truefoundry/deploy/lib/logs_utils.py,sha256=SQxRv3jDDmgHdOUMhlMaAPGYskybnBUMpst7QU_i_sc,1469
|
|
102
102
|
truefoundry/deploy/lib/messages.py,sha256=8424kj3kqCyDCX5Nr2WJZZ_UEutPoaSs_y2f9-O4yy8,1001
|
|
103
103
|
truefoundry/deploy/lib/session.py,sha256=fLdgR6ZDp8-hFl5NTON4ngnWLsMzGxvKtfpDOOw_7lo,4963
|
|
104
|
-
truefoundry/deploy/lib/util.py,sha256=
|
|
104
|
+
truefoundry/deploy/lib/util.py,sha256=QLED4zF_g_WE67MCrZQy1nrLcuiLwInLEqxYdLmOu90,5326
|
|
105
105
|
truefoundry/deploy/lib/win32.py,sha256=1RcvPTdlOAJ48rt8rCbE2Ufha2ztRqBAE9dueNXArrY,5009
|
|
106
106
|
truefoundry/deploy/lib/clients/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
107
107
|
truefoundry/deploy/lib/clients/servicefoundry_client.py,sha256=JIj0Rs5PVZzXeh2QubLaVjgMJiUkfHrIMTtZMpgBmiA,27369
|
|
@@ -115,12 +115,12 @@ truefoundry/deploy/lib/model/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NM
|
|
|
115
115
|
truefoundry/deploy/lib/model/entity.py,sha256=eBfA4trO0jUuDy0wifiu2rB_HryZrx5Kf-tRMwIQ_9g,8716
|
|
116
116
|
truefoundry/deploy/v2/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
117
117
|
truefoundry/deploy/v2/lib/__init__.py,sha256=WEiVMZXOVljzEE3tpGJil14liIn_PCDoACJ6b3tZ6sI,188
|
|
118
|
-
truefoundry/deploy/v2/lib/deploy.py,sha256=
|
|
118
|
+
truefoundry/deploy/v2/lib/deploy.py,sha256=JaLK0Mryps_2JaPB-q3NjfA0d55xsMFbIkH8VddRd_E,12873
|
|
119
119
|
truefoundry/deploy/v2/lib/deploy_workflow.py,sha256=G5BzMIbap8pgDX1eY-TITruUxQdkKhYtBmRwLL6lDeY,14342
|
|
120
120
|
truefoundry/deploy/v2/lib/deployable_patched_models.py,sha256=mUi-OjPf7bc8rzfrPLdFb79LKuDq7F36RxL4V-AXebs,6830
|
|
121
121
|
truefoundry/deploy/v2/lib/models.py,sha256=ogc1UYs1Z2nBdGSKCrde9sk8d0GxFKMkem99uqO5CmM,1148
|
|
122
|
-
truefoundry/deploy/v2/lib/patched_models.py,sha256=
|
|
123
|
-
truefoundry/deploy/v2/lib/source.py,sha256=
|
|
122
|
+
truefoundry/deploy/v2/lib/patched_models.py,sha256=gWpU7aVLVM-QFqUuekLbTO7ZJvWbaijzAuLgl1FwZC0,18345
|
|
123
|
+
truefoundry/deploy/v2/lib/source.py,sha256=nG11vrPqc2Z2bv7IMRruB-fNbSxY8jeWYNcCTEXr5s0,8622
|
|
124
124
|
truefoundry/ml/__init__.py,sha256=EEEHV7w58Krpo_W9Chd8Y3TdItfFO3LI6j6Izqc4-P8,2219
|
|
125
125
|
truefoundry/ml/constants.py,sha256=vDq72d4C9FSWqr9MMdjgTF4TuyNFApvo_6RVsSeAjB4,2837
|
|
126
126
|
truefoundry/ml/entities.py,sha256=GuwzmS7qqZJ_iz34zhla_Pg-ZNjt_3oHG2gn-LMftKk,1486
|
|
@@ -349,7 +349,7 @@ truefoundry/ml/_autogen/models/schema.py,sha256=a_bp42MMPUbwO3407m0UW2W8EOhnxZXf
|
|
|
349
349
|
truefoundry/ml/_autogen/models/signature.py,sha256=rBjpxUIsEeWM0sIyYG5uCJB18DKHR4k5yZw8TzuoP48,4987
|
|
350
350
|
truefoundry/ml/_autogen/models/utils.py,sha256=c7RtSLXhOLcP8rjuUtfnMdaKVTZvvbsmw98gPAkAFrs,24371
|
|
351
351
|
truefoundry/ml/artifact/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
352
|
-
truefoundry/ml/artifact/truefoundry_artifact_repo.py,sha256=
|
|
352
|
+
truefoundry/ml/artifact/truefoundry_artifact_repo.py,sha256=ksqnveJm_-8l4rny_cCJqAHFIZQDQyv_FSU_GjZFHSY,36136
|
|
353
353
|
truefoundry/ml/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
354
354
|
truefoundry/ml/cli/cli.py,sha256=MwpY7z_NEeJE_XIP7XbZELjNeu2vpMmohttHCKDRk54,335
|
|
355
355
|
truefoundry/ml/cli/utils.py,sha256=j6_mZ4Spn114mz3P4QQ8jx0tmorXIuyQnHXVUSDvZi4,1035
|
|
@@ -365,11 +365,11 @@ truefoundry/ml/log_types/plot.py,sha256=LDh4uy6z2P_a2oPM2lc85c0lt8utVvunohzeMawF
|
|
|
365
365
|
truefoundry/ml/log_types/pydantic_base.py,sha256=eBlw_AEyAz4iJKDP4zgJOCFWcldwQqpf7FADW1jzIQY,272
|
|
366
366
|
truefoundry/ml/log_types/utils.py,sha256=xjJ21jdPScvFmw3TbVh5NCzbzJwaqiXJyiiT4xxX1EI,335
|
|
367
367
|
truefoundry/ml/log_types/artifacts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
368
|
-
truefoundry/ml/log_types/artifacts/artifact.py,sha256=
|
|
368
|
+
truefoundry/ml/log_types/artifacts/artifact.py,sha256=OXJDaJZLGE8jA-6A8pdApfpbz1x3O-8rIMWUkG_8hYA,19940
|
|
369
369
|
truefoundry/ml/log_types/artifacts/constants.py,sha256=7blG13UXSkZVZkN8EDFqaH-a_ZonJA6pI0gwJwkIZ-s,1298
|
|
370
370
|
truefoundry/ml/log_types/artifacts/dataset.py,sha256=OgWIoT59AhMw8P01FfvUKbJ3EL6HQf_Xw8X4E3Ff5Sg,13172
|
|
371
371
|
truefoundry/ml/log_types/artifacts/general_artifact.py,sha256=yr-SQ2fhUR_sE1MB5zoHHYpGC8tizH_-t3lhsxCAULU,2747
|
|
372
|
-
truefoundry/ml/log_types/artifacts/model.py,sha256=
|
|
372
|
+
truefoundry/ml/log_types/artifacts/model.py,sha256=j4Gf0TKpi-JCOBqCdkH40pkpDLwvSk04KgQn2sK5fZI,24911
|
|
373
373
|
truefoundry/ml/log_types/artifacts/utils.py,sha256=INZhhzl6OaD6qFAyxaLJAhXhFd6wKNujMj-lq2v8p4Q,9340
|
|
374
374
|
truefoundry/ml/log_types/image/__init__.py,sha256=fcOq8yQnNj1rkLcPeIjLXBpdA1WIeiPsXOlAAvMxx7M,76
|
|
375
375
|
truefoundry/ml/log_types/image/constants.py,sha256=wLtGEOA4T5fZHSlOXPuNDLX3lpbCtwlvGKPFk_1fah0,255
|
|
@@ -387,7 +387,7 @@ truefoundry/workflow/remote_filesystem/__init__.py,sha256=LQ95ViEjJ7Ts4JcCGOxMPs
|
|
|
387
387
|
truefoundry/workflow/remote_filesystem/logger.py,sha256=em2l7D6sw7xTLDP0kQSLpgfRRCLpN14Qw85TN7ujQcE,1022
|
|
388
388
|
truefoundry/workflow/remote_filesystem/tfy_signed_url_client.py,sha256=xcT0wQmQlgzcj0nP3tJopyFSVWT1uv3nhiTIuwfXYeg,12342
|
|
389
389
|
truefoundry/workflow/remote_filesystem/tfy_signed_url_fs.py,sha256=nSGPZu0Gyd_jz0KsEE-7w_BmnTD8CVF1S8cUJoxaCbc,13305
|
|
390
|
-
truefoundry-0.
|
|
391
|
-
truefoundry-0.
|
|
392
|
-
truefoundry-0.
|
|
393
|
-
truefoundry-0.
|
|
390
|
+
truefoundry-0.12.0.dist-info/METADATA,sha256=Sk_OSFRhLRarXdP1ju69dvUYFffXcVRMXuUeY2K57Ew,2796
|
|
391
|
+
truefoundry-0.12.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
392
|
+
truefoundry-0.12.0.dist-info/entry_points.txt,sha256=xVjn7RMN-MW2-9f7YU-bBdlZSvvrwzhpX1zmmRmsNPU,98
|
|
393
|
+
truefoundry-0.12.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|