truefoundry 0.4.2rc2__py3-none-any.whl → 0.4.2rc4__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.

@@ -5,8 +5,9 @@ CREDENTIAL_FILEPATH = TFY_CONFIG_DIR / "credentials.json"
5
5
 
6
6
  TFY_HOST_ENV_KEY = "TFY_HOST"
7
7
  TFY_API_KEY_ENV_KEY = "TFY_API_KEY"
8
- SERVICEFOUNDRY_SERVER_URL_ENV_KEY = "SERVICEFOUNDRY_SERVER_URL"
8
+ TFY_CLI_LOCAL_DEV_MODE_ENV_KEY = "TFY_CLI_LOCAL_DEV_MODE"
9
9
 
10
10
  API_SERVER_RELATIVE_PATH = "api/svc"
11
+ MLFOUNDRY_SERVER_RELATIVE_PATH = "api/ml"
11
12
  VERSION_PREFIX = "v1"
12
13
  SERVICEFOUNDRY_CLIENT_MAX_RETRIES = 2
@@ -1,7 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import functools
4
- from urllib.parse import urlparse
5
4
 
6
5
  import requests
7
6
  from packaging import version
@@ -16,7 +15,7 @@ from truefoundry.common.entities import (
16
15
  )
17
16
  from truefoundry.common.request_utils import request_handling, requests_retry_session
18
17
  from truefoundry.common.utils import (
19
- append_servicefoundry_path_to_base_url,
18
+ get_tfy_servers_config,
20
19
  timed_lru_cache,
21
20
  )
22
21
  from truefoundry.logger import logger
@@ -49,10 +48,10 @@ def session_with_retries() -> requests.Session:
49
48
 
50
49
 
51
50
  @timed_lru_cache(seconds=30 * 60)
52
- def _cached_get_tenant_info(api_server_url: str) -> TenantInfo:
51
+ def _cached_get_tenant_info(api_server_url: str, tenant_host: str) -> TenantInfo:
53
52
  res = session_with_retries().get(
54
53
  url=f"{api_server_url}/{VERSION_PREFIX}/tenant-id",
55
- params={"hostName": urlparse(api_server_url).netloc},
54
+ params={"hostName": tenant_host},
56
55
  )
57
56
  res = request_handling(res)
58
57
  return TenantInfo.parse_obj(res)
@@ -71,7 +70,9 @@ class ServiceFoundryServiceClient:
71
70
  # TODO (chiragjn): Rename base_url to tfy_host
72
71
  def __init__(self, base_url: str):
73
72
  self._base_url = base_url.strip("/")
74
- self._api_server_url = append_servicefoundry_path_to_base_url(self._base_url)
73
+ tfy_servers_config = get_tfy_servers_config(self._base_url)
74
+ self._tenant_host = tfy_servers_config.tenant_host
75
+ self._api_server_url = tfy_servers_config.servicefoundry_server_url
75
76
 
76
77
  @property
77
78
  def base_url(self) -> str:
@@ -79,11 +80,16 @@ class ServiceFoundryServiceClient:
79
80
 
80
81
  @property
81
82
  def tenant_info(self) -> TenantInfo:
82
- return _cached_get_tenant_info(self._api_server_url)
83
+ return _cached_get_tenant_info(
84
+ self._api_server_url,
85
+ tenant_host=self._tenant_host,
86
+ )
83
87
 
84
88
  @property
85
89
  def python_sdk_config(self) -> PythonSDKConfig:
86
- return _cached_get_python_sdk_config(self._api_server_url)
90
+ return _cached_get_python_sdk_config(
91
+ self._api_server_url,
92
+ )
87
93
 
88
94
  @functools.cached_property
89
95
  def _min_cli_version_required(self) -> str:
@@ -3,17 +3,51 @@ import time
3
3
  from functools import lru_cache, wraps
4
4
  from time import monotonic_ns
5
5
  from typing import Callable, Generator, Optional, TypeVar
6
- from urllib.parse import urljoin, urlsplit
6
+ from urllib.parse import urljoin, urlparse
7
7
 
8
8
  from truefoundry.common.constants import (
9
9
  API_SERVER_RELATIVE_PATH,
10
- SERVICEFOUNDRY_SERVER_URL_ENV_KEY,
10
+ MLFOUNDRY_SERVER_RELATIVE_PATH,
11
+ TFY_CLI_LOCAL_DEV_MODE_ENV_KEY,
11
12
  TFY_HOST_ENV_KEY,
12
13
  )
14
+ from truefoundry.pydantic_v1 import BaseSettings
13
15
 
14
16
  T = TypeVar("T")
15
17
 
16
18
 
19
+ class _TFYServersConfig(BaseSettings):
20
+ class Config:
21
+ env_prefix = "TFY_CLI_LOCAL_"
22
+ env_file = ".tfy-cli-local.env"
23
+
24
+ tenant_host: str
25
+ servicefoundry_server_url: str
26
+ mlfoundry_server_url: str
27
+
28
+ @classmethod
29
+ def from_base_url(cls, base_url: str) -> "_TFYServersConfig":
30
+ base_url = base_url.strip("/")
31
+ return cls(
32
+ tenant_host=urlparse(base_url).netloc,
33
+ servicefoundry_server_url=urljoin(base_url, API_SERVER_RELATIVE_PATH),
34
+ mlfoundry_server_url=urljoin(base_url, MLFOUNDRY_SERVER_RELATIVE_PATH),
35
+ )
36
+
37
+
38
+ _tfy_servers_config = None
39
+
40
+
41
+ def get_tfy_servers_config(base_url: str) -> _TFYServersConfig:
42
+ global _tfy_servers_config
43
+ if _tfy_servers_config is None:
44
+ if os.getenv(TFY_CLI_LOCAL_DEV_MODE_ENV_KEY):
45
+ _tfy_servers_config = _TFYServersConfig() # type: ignore[call-arg]
46
+ else:
47
+ _tfy_servers_config = _TFYServersConfig.from_base_url(base_url)
48
+ return _tfy_servers_config
49
+
50
+
17
51
  def relogin_error_message(message: str, host: str = "HOST") -> str:
18
52
  suffix = ""
19
53
  if host == "HOST":
@@ -53,7 +87,7 @@ def poll_for_function(
53
87
  time.sleep(poll_after_secs)
54
88
 
55
89
 
56
- def validate_tfy_host(tfy_host: str) -> str:
90
+ def validate_tfy_host(tfy_host: str) -> None:
57
91
  if not (tfy_host.startswith("https://") or tfy_host.startswith("http://")):
58
92
  raise ValueError(
59
93
  f"Invalid host {tfy_host!r}. It should start with https:// or http://"
@@ -69,10 +103,3 @@ def resolve_tfy_host(tfy_host: Optional[str] = None) -> str:
69
103
  tfy_host = tfy_host.strip("/")
70
104
  validate_tfy_host(tfy_host)
71
105
  return tfy_host
72
-
73
-
74
- # TODO (chiragjn): Rename base_url to tfy_host
75
- def append_servicefoundry_path_to_base_url(base_url: str):
76
- if urlsplit(base_url).netloc.startswith("localhost"):
77
- return os.getenv(SERVICEFOUNDRY_SERVER_URL_ENV_KEY)
78
- return urljoin(base_url, API_SERVER_RELATIVE_PATH)
@@ -1,4 +1,4 @@
1
- from typing import Dict, List, Optional, Union
1
+ from typing import Any, Dict, List, Optional, Union
2
2
 
3
3
  from truefoundry.deploy.auto_gen.models import (
4
4
  DockerFileBuild,
@@ -24,7 +24,7 @@ class _BuildConfig(BaseModel):
24
24
 
25
25
 
26
26
  def build(
27
- build_configuration: Union[BaseModel, Dict],
27
+ build_configuration: Union[BaseModel, Dict[str, Any]],
28
28
  tag: str,
29
29
  extra_opts: Optional[List[str]] = None,
30
30
  ):
@@ -8,16 +8,20 @@ from truefoundry.deploy.builder.builders.tfy_notebook_buildpack.dockerfile_templ
8
8
  NotebookImageBuild,
9
9
  generate_dockerfile_content,
10
10
  )
11
+ from truefoundry.deploy.builder.utils import has_pip_conf_secret
11
12
 
12
13
  __all__ = ["generate_dockerfile_content", "build"]
13
14
 
14
15
 
15
16
  def _convert_to_dockerfile_build_config(
16
- build_configuration: NotebookImageBuild, local_dir: str
17
+ build_configuration: NotebookImageBuild,
18
+ local_dir: str,
19
+ mount_pip_conf_secret: bool = False,
17
20
  ) -> DockerFileBuild:
18
21
  dockerfile_content = generate_dockerfile_content(
19
22
  build_configuration=build_configuration,
20
23
  local_dir=local_dir,
24
+ mount_pip_conf_secret=mount_pip_conf_secret,
21
25
  )
22
26
  dockerfile_path = os.path.join(local_dir, "Dockerfile")
23
27
  with open(dockerfile_path, "w", encoding="utf8") as fp:
@@ -34,10 +38,12 @@ def build(
34
38
  build_configuration: NotebookImageBuild,
35
39
  extra_opts: Optional[List[str]] = None,
36
40
  ):
41
+ mount_pip_conf_secret = has_pip_conf_secret(extra_opts) if extra_opts else False
37
42
  with TemporaryDirectory() as local_dir:
38
43
  docker_build_configuration = _convert_to_dockerfile_build_config(
39
44
  build_configuration,
40
45
  local_dir=local_dir,
46
+ mount_pip_conf_secret=mount_pip_conf_secret,
41
47
  )
42
48
  dockerfile.build(
43
49
  tag=tag,
@@ -4,6 +4,10 @@ from typing import Literal, Optional
4
4
 
5
5
  from mako.template import Template
6
6
 
7
+ from truefoundry.deploy.builder.constants import (
8
+ PIP_CONF_BUILDKIT_SECRET_MOUNT,
9
+ PIP_CONF_SECRET_MOUNT_AS_ENV,
10
+ )
7
11
  from truefoundry.pydantic_v1 import BaseModel
8
12
 
9
13
 
@@ -28,31 +32,40 @@ USER $NB_UID
28
32
 
29
33
 
30
34
  def generate_build_script_docker_commands(
31
- build_script: Optional[str], local_dir: str
35
+ build_script: Optional[str],
36
+ local_dir: str,
37
+ mount_pip_conf_secret: bool = False,
32
38
  ) -> Optional[str]:
33
39
  if not build_script:
34
40
  return None
35
- build_script_path = None
36
- if build_script:
37
- # we add build script's hash to the file name to ensure docker cache invalidation
38
- script_hash = hashlib.sha256(build_script.encode("utf-8")).hexdigest()
39
- build_script_path = os.path.join(local_dir, f"build-script-{script_hash}.sh")
40
- with open(build_script_path, "w") as fp:
41
- fp.write(build_script)
42
- build_script_path = os.path.relpath(build_script_path, local_dir)
41
+ # we add build script's hash to the file name to ensure docker cache invalidation
42
+ script_hash = hashlib.sha256(build_script.encode("utf-8")).hexdigest()
43
+ build_script_path = os.path.join(local_dir, f"build-script-{script_hash}.sh")
44
+ with open(build_script_path, "w") as fp:
45
+ fp.write(build_script)
46
+ build_script_path = os.path.relpath(build_script_path, local_dir)
47
+ buildkit_secret_mounts = ""
48
+ environment_variables = ["DEBIAN_FRONTEND=noninteractive"]
49
+ if mount_pip_conf_secret:
50
+ buildkit_secret_mounts = PIP_CONF_BUILDKIT_SECRET_MOUNT
51
+ environment_variables.append(PIP_CONF_SECRET_MOUNT_AS_ENV)
52
+ all_environment_variables = " ".join(environment_variables)
43
53
  run_build_script_command = f"""\
44
54
  COPY {build_script_path} /tmp/user-build-script.sh
45
- RUN mkdir -p /var/log/ && DEBIAN_FRONTEND=noninteractive bash -ex /tmp/user-build-script.sh 2>&1 | tee /var/log/user-build-script-output.log
55
+ RUN {buildkit_secret_mounts} mkdir -p /var/log/ && {all_environment_variables} bash -ex /tmp/user-build-script.sh 2>&1 | tee /var/log/user-build-script-output.log
46
56
  """
47
57
  return run_build_script_command
48
58
 
49
59
 
50
60
  def generate_dockerfile_content(
51
- build_configuration: NotebookImageBuild, local_dir: str
61
+ build_configuration: NotebookImageBuild,
62
+ local_dir: str,
63
+ mount_pip_conf_secret: bool = False,
52
64
  ) -> str:
53
65
  build_script_docker_commands = generate_build_script_docker_commands(
54
66
  build_script=build_configuration.build_script,
55
67
  local_dir=local_dir,
68
+ mount_pip_conf_secret=mount_pip_conf_secret,
56
69
  )
57
70
 
58
71
  template_args = {
@@ -62,5 +75,5 @@ def generate_dockerfile_content(
62
75
 
63
76
  template = DOCKERFILE_TEMPLATE
64
77
 
65
- dockerfile_content = template.render(**template_args)
78
+ dockerfile_content: str = template.render(**template_args)
66
79
  return dockerfile_content
@@ -7,6 +7,7 @@ from truefoundry.deploy.builder.builders import dockerfile
7
7
  from truefoundry.deploy.builder.builders.tfy_python_buildpack.dockerfile_template import (
8
8
  generate_dockerfile_content,
9
9
  )
10
+ from truefoundry.deploy.builder.utils import has_pip_conf_secret
10
11
 
11
12
  __all__ = ["generate_dockerfile_content", "build"]
12
13
 
@@ -14,9 +15,11 @@ __all__ = ["generate_dockerfile_content", "build"]
14
15
  def _convert_to_dockerfile_build_config(
15
16
  build_configuration: PythonBuild,
16
17
  dockerfile_path: str,
18
+ mount_pip_conf_secret: bool = False,
17
19
  ) -> DockerFileBuild:
18
20
  dockerfile_content = generate_dockerfile_content(
19
- build_configuration=build_configuration
21
+ build_configuration=build_configuration,
22
+ mount_pip_conf_secret=mount_pip_conf_secret,
20
23
  )
21
24
  with open(dockerfile_path, "w", encoding="utf8") as fp:
22
25
  fp.write(dockerfile_content)
@@ -33,9 +36,12 @@ def build(
33
36
  build_configuration: PythonBuild,
34
37
  extra_opts: Optional[List[str]] = None,
35
38
  ):
39
+ mount_pip_conf_secret = has_pip_conf_secret(extra_opts) if extra_opts else False
36
40
  with TemporaryDirectory() as local_dir:
37
41
  docker_build_configuration = _convert_to_dockerfile_build_config(
38
- build_configuration, dockerfile_path=os.path.join(local_dir, "Dockerfile")
42
+ build_configuration,
43
+ dockerfile_path=os.path.join(local_dir, "Dockerfile"),
44
+ mount_pip_conf_secret=mount_pip_conf_secret,
39
45
  )
40
46
  dockerfile.build(
41
47
  tag=tag,
@@ -4,6 +4,10 @@ from typing import Dict, List, Optional
4
4
  from mako.template import Template
5
5
 
6
6
  from truefoundry.deploy.auto_gen.models import PythonBuild
7
+ from truefoundry.deploy.builder.constants import (
8
+ PIP_CONF_BUILDKIT_SECRET_MOUNT,
9
+ PIP_CONF_SECRET_MOUNT_AS_ENV,
10
+ )
7
11
  from truefoundry.deploy.v2.lib.patched_models import CUDAVersion
8
12
 
9
13
  # TODO (chiragjn): Switch to a non-root user inside the container
@@ -18,7 +22,7 @@ COPY ${requirements_path} ${requirements_destination_path}
18
22
  % endif
19
23
 
20
24
  % if pip_install_command is not None:
21
- RUN ${pip_install_command}
25
+ RUN ${pip_config_secret_mount} ${pip_install_command}
22
26
  % endif
23
27
 
24
28
  COPY . /app
@@ -27,7 +31,7 @@ WORKDIR /app
27
31
 
28
32
  DOCKERFILE_TEMPLATE = Template(
29
33
  """
30
- FROM --platform=linux/amd64 python:${python_version}
34
+ FROM --platform=linux/amd64 public.ecr.aws/docker/library/python:${python_version}
31
35
  ENV PATH=/virtualenvs/venv/bin:$PATH
32
36
  RUN apt update && \
33
37
  DEBIAN_FRONTEND=noninteractive apt install -y --no-install-recommends git && \
@@ -65,6 +69,11 @@ CUDA_VERSION_TO_IMAGE_TAG: Dict[str, str] = {
65
69
  CUDAVersion.CUDA_12_0_CUDNN8.value: "12.0.1-cudnn8-runtime-ubuntu22.04",
66
70
  CUDAVersion.CUDA_12_1_CUDNN8.value: "12.1.1-cudnn8-runtime-ubuntu22.04",
67
71
  CUDAVersion.CUDA_12_2_CUDNN8.value: "12.2.2-cudnn8-runtime-ubuntu22.04",
72
+ CUDAVersion.CUDA_12_3_CUDNN9.value: "12.3.2-cudnn9-runtime-ubuntu22.04",
73
+ # From 12.4+ onwards, the image tags drop the cudnn version
74
+ CUDAVersion.CUDA_12_4_CUDNN9.value: "12.4.1-cudnn-runtime-ubuntu22.04",
75
+ CUDAVersion.CUDA_12_5_CUDNN9.value: "12.5.1-cudnn-runtime-ubuntu22.04",
76
+ CUDAVersion.CUDA_12_6_CUDNN9.value: "12.6.1-cudnn-runtime-ubuntu22.04",
68
77
  }
69
78
 
70
79
 
@@ -100,7 +109,9 @@ def generate_apt_install_command(apt_packages: Optional[List[str]]) -> Optional[
100
109
 
101
110
 
102
111
  def generate_pip_install_command(
103
- requirements_path: Optional[str], pip_packages: Optional[List[str]]
112
+ requirements_path: Optional[str],
113
+ pip_packages: Optional[List[str]],
114
+ mount_pip_conf_secret: bool = False,
104
115
  ) -> Optional[str]:
105
116
  upgrade_pip_command = "python -m pip install -U pip setuptools wheel"
106
117
  final_pip_install_command = None
@@ -119,11 +130,17 @@ def generate_pip_install_command(
119
130
  if not final_pip_install_command:
120
131
  return None
121
132
 
133
+ if mount_pip_conf_secret:
134
+ final_pip_install_command = (
135
+ f"{PIP_CONF_SECRET_MOUNT_AS_ENV} {final_pip_install_command}"
136
+ )
137
+
122
138
  return " && ".join([upgrade_pip_command, final_pip_install_command])
123
139
 
124
140
 
125
141
  def generate_dockerfile_content(
126
142
  build_configuration: PythonBuild,
143
+ mount_pip_conf_secret: bool = False,
127
144
  ) -> str:
128
145
  # TODO (chiragjn): Handle recursive references to other requirements files e.g. `-r requirements-gpu.txt`
129
146
  requirements_path = resolve_requirements_txt_path(build_configuration)
@@ -133,6 +150,7 @@ def generate_dockerfile_content(
133
150
  pip_install_command = generate_pip_install_command(
134
151
  requirements_path=requirements_destination_path,
135
152
  pip_packages=build_configuration.pip_packages,
153
+ mount_pip_conf_secret=mount_pip_conf_secret,
136
154
  )
137
155
  apt_install_command = generate_apt_install_command(
138
156
  apt_packages=build_configuration.apt_packages
@@ -146,6 +164,11 @@ def generate_dockerfile_content(
146
164
  "pip_install_command": pip_install_command,
147
165
  }
148
166
 
167
+ if mount_pip_conf_secret:
168
+ template_args["pip_config_secret_mount"] = PIP_CONF_BUILDKIT_SECRET_MOUNT
169
+ else:
170
+ template_args["pip_config_secret_mount"] = ""
171
+
149
172
  if build_configuration.cuda_version:
150
173
  template = CUDA_DOCKERFILE_TEMPLATE
151
174
  template_args["nvidia_cuda_image_tag"] = CUDA_VERSION_TO_IMAGE_TAG.get(
@@ -0,0 +1,7 @@
1
+ BUILDKIT_SECRET_MOUNT_PIP_CONF_ID = "pip.conf"
2
+ PIP_CONF_BUILDKIT_SECRET_MOUNT = (
3
+ f"--mount=type=secret,id={BUILDKIT_SECRET_MOUNT_PIP_CONF_ID}"
4
+ )
5
+ PIP_CONF_SECRET_MOUNT_AS_ENV = (
6
+ f"PIP_CONFIG_FILE=/run/secrets/{BUILDKIT_SECRET_MOUNT_PIP_CONF_ID}"
7
+ )
@@ -0,0 +1,32 @@
1
+ from typing import List, Optional
2
+
3
+ from truefoundry.deploy.builder.constants import BUILDKIT_SECRET_MOUNT_PIP_CONF_ID
4
+
5
+
6
+ def _get_id_from_buildkit_secret_value(value: str) -> Optional[str]:
7
+ parts = value.split(",")
8
+ secret_config = {}
9
+ for part in parts:
10
+ kv = part.split("=", 1)
11
+ if len(kv) != 2:
12
+ continue
13
+ key, value = kv
14
+ secret_config[key] = value
15
+
16
+ if "id" in secret_config and "src" in secret_config:
17
+ return secret_config["id"]
18
+
19
+ return None
20
+
21
+
22
+ def has_pip_conf_secret(docker_build_extra_args: List[str]) -> bool:
23
+ args = [arg.strip() for arg in docker_build_extra_args]
24
+ for i, arg in enumerate(docker_build_extra_args):
25
+ if (
26
+ arg == "--secret"
27
+ and i + 1 < len(args)
28
+ and _get_id_from_buildkit_secret_value(args[i + 1])
29
+ == BUILDKIT_SECRET_MOUNT_PIP_CONF_ID
30
+ ):
31
+ return True
32
+ return False
@@ -9,7 +9,7 @@ from click.exceptions import ClickException
9
9
 
10
10
  from truefoundry.autodeploy.cli import cli as autodeploy_cli
11
11
  from truefoundry.autodeploy.exception import InvalidRequirementsException
12
- from truefoundry.deploy.cli.const import GROUP_CLS
12
+ from truefoundry.deploy.cli.const import COMMAND_CLS, GROUP_CLS
13
13
  from truefoundry.deploy.cli.util import handle_exception_wrapper
14
14
 
15
15
 
@@ -54,8 +54,13 @@ def _get_default_spec_file():
54
54
  default=True,
55
55
  help="Wait and tail the deployment progress",
56
56
  )
57
+ @click.pass_context
57
58
  @handle_exception_wrapper
58
- def deploy_command(file: str, workspace_fqn: Optional[str], wait: bool):
59
+ def deploy_command(
60
+ ctx: click.Context, file: str, workspace_fqn: Optional[str], wait: bool
61
+ ):
62
+ if ctx.invoked_subcommand is not None:
63
+ return
59
64
  from truefoundry.deploy.lib.auth.servicefoundry_session import ServiceFoundrySession
60
65
  from truefoundry.deploy.v2.lib.deployable_patched_models import Application
61
66
 
@@ -98,5 +103,44 @@ def deploy_command(file: str, workspace_fqn: Optional[str], wait: bool):
98
103
  raise UsageError(message=str(e)) from e
99
104
 
100
105
 
106
+ @deploy_command.command(name="workflow", cls=COMMAND_CLS, help="Deploy a Workflow")
107
+ @click.option(
108
+ "-n",
109
+ "--name",
110
+ required=True,
111
+ help="Name of the Workflow",
112
+ )
113
+ @click.option(
114
+ "-f",
115
+ "--file",
116
+ type=click.Path(exists=True, dir_okay=False, resolve_path=True),
117
+ required=True,
118
+ help="Path to the Workflow file. e.g. workflow.py",
119
+ )
120
+ @click.option(
121
+ "-w",
122
+ "--workspace-fqn",
123
+ "--workspace_fqn",
124
+ required=True,
125
+ help="FQN of the Workspace to deploy to.",
126
+ )
127
+ @handle_exception_wrapper
128
+ def deploy_workflow_command(name: str, workflow_file: str, workspace_fqn: str):
129
+ from truefoundry.deploy.lib.auth.servicefoundry_session import ServiceFoundrySession
130
+
131
+ try:
132
+ _ = ServiceFoundrySession()
133
+ except Exception as e:
134
+ raise ClickException(message=str(e)) from e
135
+
136
+ from truefoundry.deploy.v2.lib.deployable_patched_models import Workflow
137
+
138
+ workflow = Workflow(
139
+ name=name,
140
+ workflow_file_path=workflow_file,
141
+ )
142
+ workflow.deploy(workspace_fqn=workspace_fqn)
143
+
144
+
101
145
  def get_deploy_command():
102
146
  return deploy_command
@@ -35,9 +35,12 @@ def handle_exception(exception):
35
35
  border_style="red",
36
36
  )
37
37
  elif isinstance(exception, ConnectionError):
38
+ loc = ""
39
+ if exception.request:
40
+ loc = f" at {exception.request.url}"
38
41
  print_dict_as_table_panel(
39
42
  {
40
- "Error": "Couldn't connect to TrueFoundry. Please make sure that the provided `--host` is correct."
43
+ "Error": f"Couldn't connect to TrueFoundry{loc}. Please make sure that the provided `--host` is correct."
41
44
  },
42
45
  title="Command Failed",
43
46
  border_style="red",
@@ -84,6 +84,10 @@ class CUDAVersion(str, enum.Enum):
84
84
  CUDA_12_0_CUDNN8 = "12.0-cudnn8"
85
85
  CUDA_12_1_CUDNN8 = "12.1-cudnn8"
86
86
  CUDA_12_2_CUDNN8 = "12.2-cudnn8"
87
+ CUDA_12_3_CUDNN9 = "12.3-cudnn9"
88
+ CUDA_12_4_CUDNN9 = "12.4-cudnn9"
89
+ CUDA_12_5_CUDNN9 = "12.5-cudnn9"
90
+ CUDA_12_6_CUDNN9 = "12.6-cudnn9"
87
91
 
88
92
 
89
93
  class GPUType(str, enum.Enum):
@@ -12,16 +12,13 @@ from truefoundry.ml.clients.entities import (
12
12
  )
13
13
  from truefoundry.ml.clients.utils import http_request_safe
14
14
  from truefoundry.ml.exceptions import MlFoundryException
15
- from truefoundry.ml.run_utils import append_servicefoundry_path_to_tracking_uri
16
15
 
17
16
 
18
17
  class ServiceFoundryServiceClient(BaseServiceFoundryServiceClient):
19
18
  # TODO (chiragjn): Rename tracking_uri to tfy_host
20
19
  def __init__(self, tracking_uri: str, token: Optional[str] = None):
21
20
  super().__init__(base_url=tracking_uri)
22
- self.host_creds = HostCreds(
23
- host=append_servicefoundry_path_to_tracking_uri(tracking_uri), token=token
24
- )
21
+ self.host_creds = HostCreds(host=self._api_server_url, token=token)
25
22
 
26
23
  def get_integration_from_id(self, integration_id: str):
27
24
  integration_id = integration_id or ""
@@ -1,9 +1,7 @@
1
1
  import argparse
2
2
  import importlib
3
3
  import json
4
- import os
5
4
  from typing import Any, Dict, List, Mapping, Optional, Tuple, Union
6
- from urllib.parse import urljoin, urlsplit
7
5
 
8
6
  import numpy as np
9
7
 
@@ -21,18 +19,6 @@ def get_module(
21
19
  raise MlFoundryException(msg) from ex
22
20
 
23
21
 
24
- def append_path_to_rest_tracking_uri(tracking_uri: str):
25
- if urlsplit(tracking_uri).netloc.startswith("localhost"):
26
- return tracking_uri
27
- return urljoin(tracking_uri, "/api/ml")
28
-
29
-
30
- def append_servicefoundry_path_to_tracking_uri(tracking_uri: str):
31
- if urlsplit(tracking_uri).netloc.startswith("localhost"):
32
- return os.getenv("SERVICEFOUNDRY_SERVER_URL")
33
- return urljoin(tracking_uri, "/api/svc")
34
-
35
-
36
22
  class NumpyEncoder(json.JSONEncoder):
37
23
  """Special json encoder for numpy types"""
38
24
 
truefoundry/ml/session.py CHANGED
@@ -10,7 +10,7 @@ from truefoundry.common.credential_provider import (
10
10
  )
11
11
  from truefoundry.common.entities import Token, UserInfo
12
12
  from truefoundry.common.request_utils import urllib3_retry
13
- from truefoundry.common.utils import relogin_error_message
13
+ from truefoundry.common.utils import get_tfy_servers_config, relogin_error_message
14
14
  from truefoundry.ml.autogen.client import ( # type: ignore[attr-defined]
15
15
  ApiClient,
16
16
  Configuration,
@@ -18,9 +18,6 @@ from truefoundry.ml.autogen.client import ( # type: ignore[attr-defined]
18
18
  from truefoundry.ml.clients.entities import HostCreds
19
19
  from truefoundry.ml.exceptions import MlFoundryException
20
20
  from truefoundry.ml.logger import logger
21
- from truefoundry.ml.run_utils import (
22
- append_path_to_rest_tracking_uri,
23
- )
24
21
 
25
22
  if TYPE_CHECKING:
26
23
  from truefoundry.ml.mlfoundry_run import MlFoundryRun
@@ -99,7 +96,7 @@ class Session:
99
96
  )
100
97
 
101
98
  def get_host_creds(self) -> HostCreds:
102
- tracking_uri = append_path_to_rest_tracking_uri(self._cred_provider.base_url)
99
+ tracking_uri = get_tfy_servers_config(self.tracking_uri).mlfoundry_server_url
103
100
  return HostCreds(
104
101
  host=tracking_uri, token=self._cred_provider.token.access_token
105
102
  )
@@ -5,9 +5,9 @@ from truefoundry.workflow import PythonTaskConfig, TaskPythonBuild, task, workfl
5
5
  task_config=PythonTaskConfig(
6
6
  image=TaskPythonBuild(
7
7
  python_version="3.9",
8
- pip_packages=["truefoundry[workflow]==0.3.0rc7"],
8
+ pip_packages=["truefoundry[workflow]"],
9
9
  ),
10
- service_account="tfy-flyte-dataplane-devtest-s3",
10
+ service_account="tfy-workflows-sa",
11
11
  )
12
12
  )
13
13
  def say_hello() -> str:
@@ -7,7 +7,6 @@ from truefoundry.deploy import Image, NvidiaGPU, Resources
7
7
  from truefoundry.workflow import (
8
8
  ContainerTask,
9
9
  ContainerTaskConfig,
10
- ExecutionConfig,
11
10
  FlyteDirectory,
12
11
  PythonTaskConfig,
13
12
  TaskPythonBuild,
@@ -20,10 +19,10 @@ from truefoundry.workflow import (
20
19
  cpu_task_config = PythonTaskConfig(
21
20
  image=TaskPythonBuild(
22
21
  python_version="3.9",
23
- pip_packages=["truefoundry[workflow]==0.3.0rc7"],
22
+ pip_packages=["truefoundry[workflow]==0.4.1"],
24
23
  ),
25
24
  resources=Resources(cpu_request=0.45),
26
- service_account="tfy-flyte-dataplane-devtest-s3",
25
+ service_account="tfy-workflows-sa",
27
26
  )
28
27
 
29
28
 
@@ -49,7 +48,7 @@ def train_tokenizer() -> str:
49
48
  task_config=PythonTaskConfig(
50
49
  image=TaskPythonBuild(
51
50
  python_version="3.9",
52
- pip_packages=["truefoundry[workflow]==0.3.0rc7", "pynvml==11.5.0"],
51
+ pip_packages=["truefoundry[workflow]==0.4.1", "pynvml==11.5.0"],
53
52
  cuda_version="11.5-cudnn8",
54
53
  ),
55
54
  env={
@@ -57,16 +56,16 @@ def train_tokenizer() -> str:
57
56
  "NVIDIA_VISIBLE_DEVICES": "all",
58
57
  },
59
58
  resources=Resources(cpu_request=0.45, devices=[NvidiaGPU(name="T4", count=1)]),
60
- service_account="tfy-flyte-dataplane-devtest-s3",
59
+ service_account="tfy-workflows-sa",
61
60
  ),
62
61
  )
63
62
  def train_model(tokenizer: str) -> Tuple[FlyteDirectory, str]:
64
63
  print("Training model")
65
64
  import flytekit
66
- from pynvml import nvmlDeviceGetCount, nvmlInit
65
+ # from pynvml import nvmlDeviceGetCount, nvmlInit
67
66
 
68
- nvmlInit()
69
- assert nvmlDeviceGetCount() > 0
67
+ # nvmlInit()
68
+ # assert nvmlDeviceGetCount() > 0
70
69
 
71
70
  working_dir = flytekit.current_context().working_directory
72
71
  local_dir = Path(os.path.join(working_dir, "csv_files"))
@@ -102,10 +101,10 @@ echo = ContainerTask(
102
101
  name="echo",
103
102
  task_config=ContainerTaskConfig(
104
103
  image=Image(
105
- image_uri="bash:4.1",
104
+ image_uri="docker.io/bash:4.1",
106
105
  command=["echo", "hello"],
107
106
  ),
108
- service_account="tfy-flyte-dataplane-devtest-s3",
107
+ service_account="tfy-workflows-sa",
109
108
  ),
110
109
  )
111
110
 
@@ -117,11 +116,11 @@ def random(tokenizer: str) -> Tuple[FlyteDirectory, str]:
117
116
 
118
117
 
119
118
  @workflow(
120
- execution_configs=[
121
- ExecutionConfig(
122
- schedule="*/10 * * * *",
123
- )
124
- ]
119
+ # execution_configs=[
120
+ # ExecutionConfig(
121
+ # schedule="*/10 * * * *",
122
+ # )
123
+ # ]
125
124
  )
126
125
  def train(
127
126
  tokenizer: str = "",
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: truefoundry
3
- Version: 0.4.2rc2
3
+ Version: 0.4.2rc4
4
4
  Summary: Truefoundry CLI
5
5
  Author: Abhishek Choudhary
6
6
  Author-email: abhishek@truefoundry.com
@@ -31,7 +31,6 @@ Requires-Dist: openai (>=1.16.2,<2.0.0)
31
31
  Requires-Dist: packaging (>=20.0,<25.0)
32
32
  Requires-Dist: pandas (>=1.0.0,<3.0.0) ; python_version < "3.10"
33
33
  Requires-Dist: pandas (>=1.4.0,<3.0.0) ; python_version >= "3.10"
34
- Requires-Dist: psutil (>=5.9.0,<7.0.0)
35
34
  Requires-Dist: pydantic (>=1.8.2,<3.0.0)
36
35
  Requires-Dist: pygments (>=2.12.0,<3.0.0)
37
36
  Requires-Dist: python-dateutil (>=2.8.2,<3.0.0)
@@ -27,24 +27,26 @@ truefoundry/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
27
27
  truefoundry/cli/__main__.py,sha256=-NkhYlT3mC5MhtekueKAvCw-sWvguj0LJRpXWzvvFjc,727
28
28
  truefoundry/common/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
29
29
  truefoundry/common/auth_service_client.py,sha256=tZOa0NdATnItsMeTnEnUeTZQIgUJtpU-nvLdWtB4Px8,7978
30
- truefoundry/common/constants.py,sha256=kHP5ebp7EMfEYaOC-K8T_XPfYi7mXttYgrXYS8bOgkg,359
30
+ truefoundry/common/constants.py,sha256=JT8wcc9IxX3K_xbzXgxTp1FMQfKwnLam5XoJjhiCw1M,395
31
31
  truefoundry/common/credential_file_manager.py,sha256=1yEk1Zm2xS4G0VDFwKSZ4w0VUrcPWQ1nJnoBaz9xyKA,4251
32
32
  truefoundry/common/credential_provider.py,sha256=YQ6HKl8ZZFTg48vBZMauEAnM6IrEO3oOzM2DA47N-P0,4071
33
33
  truefoundry/common/entities.py,sha256=8O-EGPk4PKqnyoFMKUTxISCU19rz0KBnfRDJU695DhY,3797
34
34
  truefoundry/common/exceptions.py,sha256=ePpiQ_zmWe4e94gOgeMiyP_AZnKwjEBfyXsB5ScGYcI,329
35
35
  truefoundry/common/request_utils.py,sha256=-ss8033PClJOMJuS5Ue1zCFRVK7ZW9vjtva1b5G9uok,2849
36
- truefoundry/common/servicefoundry_client.py,sha256=qYSrsbFH8b7N_2oxlXfbJnWfdqHCBQ1dQ5Rr2tdp3zQ,2937
37
- truefoundry/common/utils.py,sha256=f5Av8X70vZf6eUK4Axm8q75It2-C-3o3uomA0GrFt_4,2506
36
+ truefoundry/common/servicefoundry_client.py,sha256=klohrELTFTJX-jvl9LGtdIoJiZMZRuQQB4Ho7PJ7u3s,3091
37
+ truefoundry/common/utils.py,sha256=lFiDEVoQDJoZPEN4Zun4GQz2TsfdbXfNHI41BErETq8,3320
38
38
  truefoundry/deploy/__init__.py,sha256=ugawKF2G02EmEXX35oZ2tec12d9oWN28Sf6mtGGIERY,2281
39
39
  truefoundry/deploy/auto_gen/models.py,sha256=AjbjNFwWDTIOjN_E1fSUgP-ej9nsb2OpZPhsnIRAVGs,80621
40
- truefoundry/deploy/builder/__init__.py,sha256=a1qR6nicHGcxRaeNTxWRsmDs8zsmXc7j13-I8q0qqVk,4938
40
+ truefoundry/deploy/builder/__init__.py,sha256=1qjHMNBE1poRCZW0WrG46dFM1f1IlivD5352qzsioMU,4953
41
41
  truefoundry/deploy/builder/builders/__init__.py,sha256=tlFLXqyDaKLd4iZbo4Hcu_8gOmgtL6drnXpbmQ6x1P8,636
42
42
  truefoundry/deploy/builder/builders/dockerfile.py,sha256=AXXTziCkaqIhuM_bwyD1vT1znOwemN1TKgU7eyo-KuM,1522
43
- truefoundry/deploy/builder/builders/tfy_notebook_buildpack/__init__.py,sha256=OK2lCwaPfhh7ALjNqfFBOTv7B9B3e9WDLoaSm0LWEkk,1436
44
- truefoundry/deploy/builder/builders/tfy_notebook_buildpack/dockerfile_template.py,sha256=cEjpcz2L9lEEoEcF0rzuRpgXwNkuce8dbvdBvhTqDYk,1946
45
- truefoundry/deploy/builder/builders/tfy_python_buildpack/__init__.py,sha256=n7MwUzIyn3mFqVkQqOuMeswmSPsydpYH4XMV5c8qAdQ,1381
46
- truefoundry/deploy/builder/builders/tfy_python_buildpack/dockerfile_template.py,sha256=vFmFeK38-t8booJEGREapEjrIL8xnyOQeRSJQq7d3ZQ,6183
43
+ truefoundry/deploy/builder/builders/tfy_notebook_buildpack/__init__.py,sha256=UmMcTY-8MrLY3H5owpn6ax-VePQl4MiMTmHlQ9qEtQw,1742
44
+ truefoundry/deploy/builder/builders/tfy_notebook_buildpack/dockerfile_template.py,sha256=nRG3yXhIQ3Taq1B1loQWazQd05A3nrp5zKDYvNZh87s,2487
45
+ truefoundry/deploy/builder/builders/tfy_python_buildpack/__init__.py,sha256=XNJ3MKWqyWIbFNnUQMpB8oVC5Pt5Wsm_bRKbvkXRIG8,1696
46
+ truefoundry/deploy/builder/builders/tfy_python_buildpack/dockerfile_template.py,sha256=dccCNOUKbK1X8F4f2J4ddSTCturvzQKx6H23xxJdCTk,7202
47
+ truefoundry/deploy/builder/constants.py,sha256=eIukBjD6I4KvEmAPpdbPlPPr76yhS-uNr3RVFkzEdgs,257
47
48
  truefoundry/deploy/builder/docker_service.py,sha256=vQS15790njzlFJZ3JW6txYLBdT11ltxqqpf78ZFL_Ng,5208
49
+ truefoundry/deploy/builder/utils.py,sha256=9RZnkhoHFTRUt_x3nck0aVz7cLpzA3jiwQH-ZZZrjf8,938
48
50
  truefoundry/deploy/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
49
51
  truefoundry/deploy/cli/cli.py,sha256=o19n7MsMzXXXG3GlpRYaxX3l9Xvtof-iPK4-y31Dw9k,2811
50
52
  truefoundry/deploy/cli/commands/__init__.py,sha256=oOstv608ueOJTxR3qlQbZBIdo-FsFe2O0NYNOXi01-s,1276
@@ -53,7 +55,7 @@ truefoundry/deploy/cli/commands/build_command.py,sha256=DQ7NARgkIgV4z0Zdnl3zMDKU
53
55
  truefoundry/deploy/cli/commands/build_logs_command.py,sha256=WrPOlFec_wwuzdJmKZ8mjca-oFVvxgfblcqj2LlhWJA,2804
54
56
  truefoundry/deploy/cli/commands/create_command.py,sha256=ZjA4EP1jHYuVE1zx0kN-giBr3y0sEiXnu8xMsNyD2Rg,1850
55
57
  truefoundry/deploy/cli/commands/delete_command.py,sha256=4tyIameA1pVu9uZZNJPK6rqdV-cJogf51iCCrG-9noI,2390
56
- truefoundry/deploy/cli/commands/deploy_command.py,sha256=f3Bd0EClT4y6Eahw0pX2MFKiRD29j5kHlWVK5rbvK20,2858
58
+ truefoundry/deploy/cli/commands/deploy_command.py,sha256=ixn3uQoDRfJ9D8GOMwXJ9W9VbyNce9Qzb3Mx7h5InRM,4018
57
59
  truefoundry/deploy/cli/commands/get_command.py,sha256=w7h5C4bJpmHJ99rgiGg9J_X0xi8aZUeB6Q-SoZUV1tg,5979
58
60
  truefoundry/deploy/cli/commands/list_command.py,sha256=cFARY22L5xspBX7TWsx41IF4RiRMok7KBwv7hQRFXNs,4498
59
61
  truefoundry/deploy/cli/commands/login_command.py,sha256=WV4Ad8PJ2_yNfCJi1VWW2GNwU6khZ2sWZbKebxJ7oVM,1038
@@ -68,7 +70,7 @@ truefoundry/deploy/cli/config.py,sha256=tf8w4UfVzcC6eYkENvuuCPYt_V3sqVpO1bclORV9
68
70
  truefoundry/deploy/cli/console.py,sha256=9-dMy4YPisCJQziRKTg8Qa0UJnOGl1soiUnJjsnLDvE,242
69
71
  truefoundry/deploy/cli/const.py,sha256=dVHPo1uAiDSSMXwXoT2mR5kNQjExT98QNVRz98Hz_Ts,510
70
72
  truefoundry/deploy/cli/display_util.py,sha256=gq8EBdpBMHUzYQp_hxOg9EOYi08FIHgOVFCqXqC2tuo,3044
71
- truefoundry/deploy/cli/util.py,sha256=n2-YzdYkyJV1w7XzzWCLtksoaY35I6tM58T_qNpm4vY,3587
73
+ truefoundry/deploy/cli/util.py,sha256=bxbNEX3mbhtDpXw3b2GAnbxe0xvCF9N1sCMK6yatz0Q,3689
72
74
  truefoundry/deploy/core/__init__.py,sha256=j61bMWj4BkWihdssKMSFhieo7afJDtpc7qO7zk1rDB4,140
73
75
  truefoundry/deploy/core/login.py,sha256=N2VrW3nlBzoyoYulkipxwQvCpjBhi3sfsmhxK1ktWhg,236
74
76
  truefoundry/deploy/core/logout.py,sha256=TpWLq4_DsxYS5GX2OJQGDhekNOfiOLb-vO5khQueHXw,80
@@ -113,7 +115,7 @@ truefoundry/deploy/v2/lib/deploy.py,sha256=HIcY3SzQ5lWl7avuuKi3J0Z-PBES6Sf4hgMK-
113
115
  truefoundry/deploy/v2/lib/deploy_workflow.py,sha256=WhlrBuRf7r83qoQdTZSQzHt635fw9D4_qQIqusFWGag,12372
114
116
  truefoundry/deploy/v2/lib/deployable_patched_models.py,sha256=MROgMxhn9hDEAKwJSWl3iz12tUVvRKzEtqF2QUT6dAk,3343
115
117
  truefoundry/deploy/v2/lib/models.py,sha256=pSolLMTArDuYpeNsmeeS5DWliloN_iCDfZSpRllMHUg,1120
116
- truefoundry/deploy/v2/lib/patched_models.py,sha256=qL3N7y6zf7jywx6uY-yMxsH65NB367V_82o47ZYJt1I,13820
118
+ truefoundry/deploy/v2/lib/patched_models.py,sha256=sokVDUdnhe3qx6dXlHM0shbf6HvSlF72-mvi8Lzt_Y8,13968
117
119
  truefoundry/deploy/v2/lib/source.py,sha256=VHKuFREiixUP40D3Mrz-TA70spu1M0RbCzl--qwlFaY,9263
118
120
  truefoundry/langchain/__init__.py,sha256=zeYKxKrQhfYXQuBec3wvB_ZqKowDUUjLUKUhbiu9ZFs,558
119
121
  truefoundry/langchain/deprecated.py,sha256=8tfLHXwcifGl7DYhMNfzc4zRVCVqEgARg5BsbZp11NE,10835
@@ -296,7 +298,7 @@ truefoundry/ml/cli/commands/__init__.py,sha256=diDUiRUX4l6TtNLI4iF-ZblczkELM7FRV
296
298
  truefoundry/ml/cli/commands/download.py,sha256=cbz9KijiLKXj4-twlig3xZLTVRNm4fnjwpy0leZr31w,2342
297
299
  truefoundry/ml/clients/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
298
300
  truefoundry/ml/clients/entities.py,sha256=sNP4DnAVdQoMfc06s0r3VTzKHTo7jmxAOuTlQOVmsMs,151
299
- truefoundry/ml/clients/servicefoundry_client.py,sha256=w8fgZWZF_JjRpL_ZRmLw1BiI7aqDHnJcAXluBgwft0s,1735
301
+ truefoundry/ml/clients/servicefoundry_client.py,sha256=nmKrWBd7P0VEDGjPHZ8_scX3Xo9tv3wZSWlTIBwGptU,1597
300
302
  truefoundry/ml/clients/utils.py,sha256=c0LdC8moejs-Zm30hu1sCqifLEmqhdq4SfZ_m0nUIDk,4402
301
303
  truefoundry/ml/constants.py,sha256=vDq72d4C9FSWqr9MMdjgTF4TuyNFApvo_6RVsSeAjB4,2837
302
304
  truefoundry/ml/entities.py,sha256=si5GAqZsWzKu5MPrU4Hk6se7bebHOYhTiNw69ai-Uk8,1485
@@ -324,23 +326,23 @@ truefoundry/ml/log_types/utils.py,sha256=xjJ21jdPScvFmw3TbVh5NCzbzJwaqiXJyiiT4xx
324
326
  truefoundry/ml/logger.py,sha256=VT-BF3BnBYTWVq87O58F0c8uXMu94gYzsiFlGY3_7Ao,458
325
327
  truefoundry/ml/mlfoundry_api.py,sha256=I2T8tXeAIWpD8EH05fm80mNyX6cs2S1ORI4qoo0HTpQ,60847
326
328
  truefoundry/ml/mlfoundry_run.py,sha256=rNJl130iJkpjW3MNoe5-d_J9VJJQBqWHEJCfYeiZCbE,45123
327
- truefoundry/ml/run_utils.py,sha256=dzbQ_TGkSCYO-gg8tlr5tglR0p2SIQdy0wl4IEQE5JA,2899
328
- truefoundry/ml/session.py,sha256=_WmaGNiZCwQVmB-brbX-z38nFvuqP8f7jGxfqJoq3TM,5385
329
+ truefoundry/ml/run_utils.py,sha256=0W208wSLUrbdfk2pjNcZlkUi9bNxG2JORqoe-5rVqHI,2423
330
+ truefoundry/ml/session.py,sha256=Rvq419hdLNBt0KUzKn7jGvKKg9LI_gafOHcw-lFceAE,5330
329
331
  truefoundry/ml/validation_utils.py,sha256=XBSUd9OoyriWJpT3M5LKz17iWY3yVMr3hM5vdaVjtf0,12082
330
332
  truefoundry/pydantic_v1.py,sha256=jSuhGtz0Mbk1qYu8jJ1AcnIDK4oxUsdhALc4spqstmM,345
331
333
  truefoundry/version.py,sha256=bqiT4Q-VWrTC6P4qfK43mez-Ppf-smWfrl6DcwV7mrw,137
332
334
  truefoundry/workflow/__init__.py,sha256=hkDVrnG95duO-9XEmdjgrsvyhjQUVqyeQ1-dADB1QuE,935
333
335
  truefoundry/workflow/container_task.py,sha256=8arieePsX4__OnG337hOtCiNgJwtKJJCsZcmFmCBJtk,402
334
336
  truefoundry/workflow/example/deploy.sh,sha256=wfbPRrCi04WYRqCf4g-Xo12uWbcqPD6G_Tz0lV0jU_U,60
335
- truefoundry/workflow/example/hello_world_package/workflow.py,sha256=ACWJJWTY5NhYyU_dAEfdSqXgyLuNXPRDpOBuUkTEzhU,459
336
- truefoundry/workflow/example/package/test_workflow.py,sha256=-CeCcMyI3fjRGSkzfmmnLcE2aFxceCUpEXx8dql8MBE,4015
337
+ truefoundry/workflow/example/hello_world_package/workflow.py,sha256=IkRKfPY5BcvLPo_PVuNbZKK9PPJ93LRkzb1a3RKQYOw,435
338
+ truefoundry/workflow/example/package/test_workflow.py,sha256=TUcvYCGz4IbzF9bQJAfB-6Wd2wx-0RKcuIpUG0t6d8c,3972
337
339
  truefoundry/workflow/example/truefoundry.yaml,sha256=LlPrMADSPJsiXRoK76N_RVjX1bnZ3FH1u2jXrwLfR9I,226
338
340
  truefoundry/workflow/example/workflow.yaml,sha256=YtYdKXMuW_08gfEo21XSculj2MGI2lfEnGF8qCT8NKE,2858
339
341
  truefoundry/workflow/map_task.py,sha256=2m3qGXQ90k9LdS45q8dqCCECc3qr8t2m_LMCVd1mZ7g,1737
340
342
  truefoundry/workflow/python_task.py,sha256=SRXRLC4vdBqGjhkwuaY39LEWN6iPCpJAuW17URRdWTY,1128
341
343
  truefoundry/workflow/task.py,sha256=ToitYiKcNzFCtOVQwz1W8sRjbR97eVS7vQBdbgUQtKg,1779
342
344
  truefoundry/workflow/workflow.py,sha256=WaTqUjhwfAXDWu4E5ehuwAxrCbDJkoAf1oWmR2E9Qy0,4575
343
- truefoundry-0.4.2rc2.dist-info/METADATA,sha256=8wBExyVvKXs8p3xYsQf8p6uGf8Mb16m8DK2GlgHt78o,3140
344
- truefoundry-0.4.2rc2.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
345
- truefoundry-0.4.2rc2.dist-info/entry_points.txt,sha256=TXvUxQkI6zmqJuycPsyxEIMr3oqfDjgrWj0m_9X12x4,95
346
- truefoundry-0.4.2rc2.dist-info/RECORD,,
345
+ truefoundry-0.4.2rc4.dist-info/METADATA,sha256=eVFBEHzH-io21OISm7nj8Ky_kjdLlSfPCjekRViZ_cQ,3101
346
+ truefoundry-0.4.2rc4.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
347
+ truefoundry-0.4.2rc4.dist-info/entry_points.txt,sha256=TXvUxQkI6zmqJuycPsyxEIMr3oqfDjgrWj0m_9X12x4,95
348
+ truefoundry-0.4.2rc4.dist-info/RECORD,,