truefoundry 0.3.0rc9__py3-none-any.whl → 0.3.0rc11__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.

@@ -16,6 +16,7 @@ from truefoundry.deploy.lib.dao.application import (
16
16
  list_job_runs,
17
17
  terminate_job_run,
18
18
  trigger_job,
19
+ trigger_workflow,
19
20
  )
20
21
  from truefoundry.deploy.lib.dao.version import (
21
22
  get_version as get_application_version,
@@ -13,6 +13,7 @@ from truefoundry.deploy.cli.commands import (
13
13
  get_logout_command,
14
14
  get_patch_application_command,
15
15
  get_patch_command,
16
+ get_trigger_command,
16
17
  )
17
18
  from truefoundry.deploy.cli.config import CliConfig
18
19
  from truefoundry.deploy.cli.const import GROUP_CLS
@@ -36,6 +37,7 @@ def create_truefoundry_cli():
36
37
  cli.add_command(get_deploy_command())
37
38
  cli.add_command(get_patch_application_command())
38
39
  cli.add_command(get_delete_command())
40
+ cli.add_command(get_trigger_command())
39
41
 
40
42
  if not (sys.platform.startswith("win32") or sys.platform.startswith("cygwin")):
41
43
  cli.add_command(get_patch_command())
@@ -82,6 +82,64 @@ def trigger_job(application_fqn: str, command: Optional[Sequence[str]], params):
82
82
  )
83
83
 
84
84
 
85
+ @click.command(
86
+ name="workflow",
87
+ cls=COMMAND_CLS,
88
+ context_settings={"ignore_unknown_options": True, "allow_extra_args": True},
89
+ )
90
+ @click.option(
91
+ "--application-fqn",
92
+ "--application_fqn",
93
+ type=click.STRING,
94
+ required=True,
95
+ help="FQN of the workflow application",
96
+ )
97
+ @click.argument(
98
+ "inputs",
99
+ type=click.STRING,
100
+ nargs=-1,
101
+ required=False,
102
+ )
103
+ @handle_exception_wrapper
104
+ def trigger_workflow(application_fqn: str, inputs):
105
+ """
106
+ Trigger a Workflow on TrueFoundry
107
+
108
+ [b]tfy trigger workflow --application-fqn "my-cluster:my-workspace:my-workflow"[/]
109
+
110
+ \n
111
+ Additionally, you can pass inputs (if defined in the workflow)\n\n
112
+
113
+ Passing inputs:
114
+
115
+ [b]tfy trigger workflow --application-fqn "my-cluster:my-workspace:my-workflow" -- --input1_name input1_value --input2_name input2_value ...[/]
116
+ """
117
+ if inputs:
118
+ inputs_dict = {}
119
+ if len(inputs) % 2 != 0:
120
+ raise ClickException(
121
+ f"Found odd number of argument pairs: {inputs}. "
122
+ "Perhaps you forgot to pass a value for one of the inputs? "
123
+ "inputs for workflow should be passed in the "
124
+ "format `--input1_name input1_value --input2_name input2_value ...`"
125
+ )
126
+ for i in range(0, len(inputs), 2):
127
+ key = inputs[i]
128
+ value = inputs[i + 1]
129
+ if not key.startswith("--"):
130
+ raise ClickException(
131
+ f"Got ambiguous argument {key!r} in inputs: {inputs}. "
132
+ f"input names should be prefixed with '--' i.e. "
133
+ "inputs for workflow should be passed in the "
134
+ "format `--input1_name input1_value --input2_name input2_value ...`"
135
+ )
136
+ key = key.lstrip("-")
137
+ inputs_dict[key] = value
138
+
139
+ application.trigger_workflow(application_fqn=application_fqn, inputs=inputs)
140
+
141
+
85
142
  def get_trigger_command():
86
143
  trigger_command.add_command(trigger_job)
144
+ trigger_command.add_command(trigger_workflow)
87
145
  return trigger_command
@@ -1,4 +1,5 @@
1
1
  import time
2
+ from abc import ABC, abstractmethod
2
3
 
3
4
  import requests
4
5
 
@@ -9,17 +10,116 @@ from truefoundry.deploy.lib.model.entity import DeviceCode, Token
9
10
  from truefoundry.logger import logger
10
11
 
11
12
 
12
- class AuthServiceClient:
13
+ class AuthServiceClient(ABC):
13
14
  def __init__(self, base_url):
14
15
  from truefoundry.deploy.lib.clients.servicefoundry_client import (
15
16
  ServiceFoundryServiceClient,
16
17
  )
17
18
 
18
19
  client = ServiceFoundryServiceClient(init_session=False, base_url=base_url)
19
- tenant_info = client.get_tenant_info()
20
20
 
21
- self._auth_server_url = tenant_info.auth_server_url
22
- self._tenant_name = tenant_info.tenant_name
21
+ self._api_server_url = client._api_server_url
22
+ self._auth_server_url = client.tenant_info.auth_server_url
23
+ self._tenant_name = client.tenant_info.tenant_name
24
+
25
+ @classmethod
26
+ def from_base_url(cls, base_url: str) -> "AuthServiceClient":
27
+ from truefoundry.deploy.lib.clients.servicefoundry_client import (
28
+ ServiceFoundryServiceClient,
29
+ )
30
+
31
+ client = ServiceFoundryServiceClient(init_session=False, base_url=base_url)
32
+ if client.python_sdk_config.use_sfy_server_auth_apis:
33
+ return ServiceFoundryServerAuthServiceClient(base_url)
34
+ return AuthServerServiceClient(base_url)
35
+
36
+ @abstractmethod
37
+ def refresh_token(self, token: Token, host: str = None) -> Token: ...
38
+
39
+ @abstractmethod
40
+ def get_device_code(self) -> DeviceCode: ...
41
+
42
+ @abstractmethod
43
+ def get_token_from_device_code(
44
+ self, device_code: str, timeout: float = 60, poll_interval_seconds: int = 1
45
+ ) -> Token: ...
46
+
47
+
48
+ class ServiceFoundryServerAuthServiceClient(AuthServiceClient):
49
+ def __init__(self, base_url):
50
+ super().__init__(base_url)
51
+
52
+ def refresh_token(self, token: Token, host: str = None) -> Token:
53
+ host_arg_str = f"--host {host}" if host else "--host HOST"
54
+ if not token.refresh_token:
55
+ # TODO: Add a way to propagate error messages without traceback to the output interface side
56
+ raise Exception(
57
+ f"Unable to resume login session. Please log in again using `tfy login {host_arg_str} --relogin`"
58
+ )
59
+ url = f"{self._api_server_url}/{VERSION_PREFIX}/oauth2/token"
60
+ data = {
61
+ "tenantName": token.tenant_name,
62
+ "refreshToken": token.refresh_token,
63
+ "grantType": "refresh_token",
64
+ "returnJWT": True,
65
+ }
66
+ res = requests.post(url, json=data)
67
+ try:
68
+ res = request_handling(res)
69
+ return Token.parse_obj(res)
70
+ except BadRequestException as ex:
71
+ raise Exception(
72
+ f"Unable to resume login session. Please log in again using `tfy login {host_arg_str} --relogin`"
73
+ ) from ex
74
+
75
+ def get_device_code(self) -> DeviceCode:
76
+ url = f"{self._api_server_url}/{VERSION_PREFIX}/oauth2/device-authorize"
77
+ data = {"tenantName": self._tenant_name}
78
+ res = requests.post(url, json=data)
79
+ res = request_handling(res)
80
+ # TODO: temporary cleanup of incorrect attributes
81
+ res = {"userCode": res.get("userCode"), "deviceCode": res.get("deviceCode")}
82
+ return DeviceCode.parse_obj(res)
83
+
84
+ def get_token_from_device_code(
85
+ self, device_code: str, timeout: float = 60, poll_interval_seconds: int = 1
86
+ ) -> Token:
87
+ timeout = timeout or 60
88
+ poll_interval_seconds = poll_interval_seconds or 1
89
+ url = f"{self._api_server_url}/{VERSION_PREFIX}/oauth2/token"
90
+ data = {
91
+ "tenantName": self._tenant_name,
92
+ "deviceCode": device_code,
93
+ "grantType": "device_code",
94
+ "returnJWT": True,
95
+ }
96
+ response = requests.post(url=url, json=data)
97
+ start_time = time.monotonic()
98
+
99
+ for response in poll_for_function(
100
+ requests.post, poll_after_secs=poll_interval_seconds, url=url, json=data
101
+ ):
102
+ if response.status_code == 201:
103
+ response = response.json()
104
+ return Token.parse_obj(response)
105
+ elif response.status_code == 202:
106
+ logger.debug("User has not authorized yet. Checking again.")
107
+ else:
108
+ raise Exception(
109
+ "Failed to get token using device code. "
110
+ f"status_code {response.status_code},\n {response.text}"
111
+ )
112
+ time_elapsed = time.monotonic() - start_time
113
+ if time_elapsed > timeout:
114
+ logger.warning("Polled server for %s secs.", int(time_elapsed))
115
+ break
116
+
117
+ raise Exception(f"Did not get authorized within {timeout} seconds.")
118
+
119
+
120
+ class AuthServerServiceClient(AuthServiceClient):
121
+ def __init__(self, base_url):
122
+ super().__init__(base_url)
23
123
 
24
124
  def refresh_token(self, token: Token, host: str = None) -> Token:
25
125
  host_arg_str = f"--host {host}" if host else "--host HOST"
@@ -33,7 +133,7 @@ class AuthServiceClient:
33
133
  "tenantName": token.tenant_name,
34
134
  "refreshToken": token.refresh_token,
35
135
  }
36
- res = requests.post(url, data=data)
136
+ res = requests.post(url, json=data)
37
137
  try:
38
138
  res = request_handling(res)
39
139
  return Token.parse_obj(res)
@@ -45,12 +145,12 @@ class AuthServiceClient:
45
145
  def get_device_code(self) -> DeviceCode:
46
146
  url = f"{self._auth_server_url}/api/{VERSION_PREFIX}/oauth/device"
47
147
  data = {"tenantName": self._tenant_name}
48
- res = requests.post(url, data=data)
148
+ res = requests.post(url, json=data)
49
149
  res = request_handling(res)
50
150
  return DeviceCode.parse_obj(res)
51
151
 
52
152
  def get_token_from_device_code(
53
- self, device_code: str, timeout: float = 60
153
+ self, device_code: str, timeout: float = 60, poll_interval_seconds: int = 1
54
154
  ) -> Token:
55
155
  url = f"{self._auth_server_url}/api/{VERSION_PREFIX}/oauth/device/token"
56
156
  data = {
@@ -61,7 +161,7 @@ class AuthServiceClient:
61
161
  poll_interval_seconds = 1
62
162
 
63
163
  for response in poll_for_function(
64
- requests.post, poll_after_secs=poll_interval_seconds, url=url, data=data
164
+ requests.post, poll_after_secs=poll_interval_seconds, url=url, json=data
65
165
  ):
66
166
  if response.status_code == 201:
67
167
  response = response.json()
@@ -44,7 +44,7 @@ class EnvCredentialProvider(CredentialProvider):
44
44
  # TODO: Read host from cred file as well.
45
45
  base_url = resolve_base_url().strip("/")
46
46
  self._host = base_url
47
- self._auth_service = AuthServiceClient(base_url=base_url)
47
+ self._auth_service = AuthServiceClient.from_base_url(base_url=base_url)
48
48
 
49
49
  servicefoundry_client = ServiceFoundryServiceClient(
50
50
  init_session=False, base_url=base_url
@@ -82,7 +82,7 @@ class FileCredentialProvider(CredentialProvider):
82
82
  self._token = self._last_cred_file_content.to_token()
83
83
  self._host = self._last_cred_file_content.host
84
84
 
85
- self._auth_service = AuthServiceClient(base_url=self._host)
85
+ self._auth_service = AuthServiceClient.from_base_url(base_url=self._host)
86
86
 
87
87
  @staticmethod
88
88
  def can_provide() -> bool:
@@ -26,12 +26,14 @@ from truefoundry.deploy.lib.model.entity import (
26
26
  Deployment,
27
27
  DockerRegistryCredentials,
28
28
  JobRun,
29
+ PythonSDKConfig,
29
30
  TenantInfo,
30
31
  Token,
31
32
  TriggerJobResult,
32
33
  Workspace,
33
34
  WorkspaceResources,
34
35
  )
36
+ from truefoundry.deploy.lib.util import timed_lru_cache
35
37
  from truefoundry.deploy.lib.win32 import allow_interrupt
36
38
  from truefoundry.deploy.v2.lib.models import (
37
39
  AppDeploymentStatusResponse,
@@ -93,6 +95,24 @@ def check_min_cli_version(fn):
93
95
  return inner
94
96
 
95
97
 
98
+ @timed_lru_cache(seconds=30 * 60)
99
+ def _cached_get_tenant_info(api_server_url: str) -> TenantInfo:
100
+ res = requests.get(
101
+ url=f"{api_server_url}/v1/tenant-id",
102
+ params={"hostName": urlparse(api_server_url).netloc},
103
+ )
104
+ res = request_handling(res)
105
+ return TenantInfo.parse_obj(res)
106
+
107
+
108
+ @timed_lru_cache(seconds=30 * 60)
109
+ def _cached_get_python_sdk_config(api_server_url: str) -> PythonSDKConfig:
110
+ url = f"{api_server_url}/v1/min-cli-version"
111
+ res = requests.get(url)
112
+ res = request_handling(res)
113
+ return PythonSDKConfig.parse_obj(res)
114
+
115
+
96
116
  class ServiceFoundryServiceClient:
97
117
  def __init__(self, init_session: bool = True, base_url: Optional[str] = None):
98
118
  self._session: Optional[ServiceFoundrySession] = None
@@ -111,20 +131,19 @@ class ServiceFoundryServiceClient:
111
131
  def base_url(self) -> str:
112
132
  return self._base_url
113
133
 
114
- def get_tenant_info(self) -> TenantInfo:
115
- res = requests.get(
116
- url=f"{self._api_server_url}/v1/tenant-id",
117
- params={"hostName": urlparse(self._api_server_url).netloc},
118
- )
119
- res = request_handling(res)
120
- return TenantInfo.parse_obj(res)
134
+ @property
135
+ def tenant_info(self) -> TenantInfo:
136
+ return _cached_get_tenant_info(self._api_server_url)
137
+
138
+ @property
139
+ def python_sdk_config(self) -> PythonSDKConfig:
140
+ return _cached_get_python_sdk_config(self._api_server_url)
121
141
 
122
142
  @functools.cached_property
123
143
  def _min_cli_version_required(self) -> str:
124
- url = f"{self._api_server_url}/v1/min-cli-version"
125
- res = requests.get(url)
126
- res = request_handling(res)
127
- return res["truefoundryCliMinVersion"]
144
+ return _cached_get_python_sdk_config(
145
+ self._api_server_url
146
+ ).truefoundry_cli_min_version
128
147
 
129
148
  def _get_header(self):
130
149
  if not self._session:
@@ -616,6 +635,12 @@ class ServiceFoundryServiceClient:
616
635
  response = request_handling(res)
617
636
  return TriggerJobResult.parse_obj(response)
618
637
 
638
+ def trigger_workflow(self, application_id: str, inputs: Dict[str, Any]):
639
+ url = f"{self._api_server_url}/{VERSION_PREFIX}/workflow/{application_id}/executions"
640
+ res = requests.post(url, json=inputs, headers=self._get_header())
641
+ response = request_handling(res)
642
+ return response
643
+
619
644
  @check_min_cli_version
620
645
  def get_docker_registry_creds(
621
646
  self, docker_registry_fqn: str, cluster_id: str
@@ -241,3 +241,23 @@ def terminate_job_run(
241
241
  job_run_name=job_run_name,
242
242
  )
243
243
  return response
244
+
245
+
246
+ def trigger_workflow(application_fqn: str, inputs: Optional[Dict[str, Any]] = None):
247
+ inputs = inputs or {}
248
+ client = ServiceFoundryServiceClient()
249
+ _application_info = client.get_application_info_by_fqn(
250
+ application_fqn=application_fqn
251
+ )
252
+ application_info = client.get_application_info(
253
+ application_id=_application_info.applicationId
254
+ )
255
+ client.trigger_workflow(
256
+ application_id=application_info.id,
257
+ inputs=inputs,
258
+ )
259
+ logger.info(f"Started Execution for Workflow: {application_info.name}")
260
+ executions_page = (
261
+ f"{client.base_url.strip('/')}/deployments/{application_info.id}?tab=executions"
262
+ )
263
+ logger.info(f"You can check the executions at {executions_page}")
@@ -297,6 +297,11 @@ class CredentialsFileContent(BaseModel):
297
297
  class DeviceCode(BaseModel):
298
298
  user_code: str = Field(alias="userCode")
299
299
  device_code: str = Field(alias="deviceCode")
300
+ verification_url: Optional[str] = Field(alias="verificationURI")
301
+ complete_verification_url: Optional[str] = Field(alias="verificationURIComplete")
302
+ expires_in_seconds: int = Field(alias="expiresInSeconds", default=60)
303
+ interval_in_seconds: int = Field(alias="intervalInSeconds", default=1)
304
+ message: Optional[str] = Field(alias="message")
300
305
 
301
306
  class Config:
302
307
  allow_population_by_field_name = True
@@ -306,6 +311,18 @@ class DeviceCode(BaseModel):
306
311
  return f"{auth_host}/authorize/device?userCode={self.user_code}"
307
312
 
308
313
 
314
+ class PythonSDKConfig(BaseModel):
315
+ min_version: str = Field(alias="minVersion")
316
+ truefoundry_cli_min_version: str = Field(alias="truefoundryCliMinVersion")
317
+ use_sfy_server_auth_apis: Optional[bool] = Field(
318
+ alias="useSFYServerAuthAPIs", default=False
319
+ )
320
+
321
+ class Config:
322
+ allow_population_by_field_name = True
323
+ allow_mutation = False
324
+
325
+
309
326
  class JobRun(Base):
310
327
  name: str
311
328
  applicationName: str
@@ -92,7 +92,7 @@ def login(
92
92
  api_key=api_key, servicefoundry_client=servicefoundry_client
93
93
  )
94
94
  else:
95
- auth_service = AuthServiceClient(base_url=host)
95
+ auth_service = AuthServiceClient.from_base_url(base_url=host)
96
96
  # interactive login
97
97
  token = _login_with_device_code(base_url=host, auth_service=auth_service)
98
98
 
@@ -136,11 +136,23 @@ def _login_with_device_code(
136
136
  ) -> Token:
137
137
  logger.debug("Logging in with device code")
138
138
  device_code = auth_service.get_device_code()
139
- url_to_go = device_code.get_user_clickable_url(auth_host=base_url)
140
- output_hook.print_line(f"Opening:- {url_to_go}")
141
- output_hook.print(
142
- "Please click on the above link if it is not "
143
- "automatically opened in a browser window."
139
+ auto_open_url = None
140
+ message = "Please click on the above link if it is not automatically opened in a browser window."
141
+ if device_code.complete_verification_url:
142
+ auto_open_url = device_code.complete_verification_url
143
+ elif device_code.verification_url:
144
+ if device_code.message:
145
+ message = device_code.message
146
+ else:
147
+ message = f"Please open the following URL in a browser and enter the code {device_code.user_code} when prompted: {device_code.verification_url}"
148
+ else:
149
+ auto_open_url = device_code.get_user_clickable_url(auth_host=base_url)
150
+ output_hook.print_line(message)
151
+ if auto_open_url:
152
+ output_hook.print_line(f"Opening:- {auto_open_url}")
153
+ click.launch(auto_open_url)
154
+ return auth_service.get_token_from_device_code(
155
+ device_code=device_code.device_code,
156
+ timeout=device_code.expires_in_seconds,
157
+ poll_interval_seconds=device_code.interval_in_seconds,
144
158
  )
145
- click.launch(url_to_go)
146
- return auth_service.get_token_from_device_code(device_code=device_code.device_code)
@@ -1,5 +1,7 @@
1
1
  import os
2
2
  import re
3
+ from functools import lru_cache, wraps
4
+ from time import monotonic_ns
3
5
  from typing import Union
4
6
 
5
7
  from truefoundry.deploy.lib.const import (
@@ -68,3 +70,21 @@ def find_list_paths(data, parent_key="", sep="."):
68
70
  new_key = f"{parent_key}[{i}]"
69
71
  list_paths.extend(find_list_paths(value, new_key, sep))
70
72
  return list_paths
73
+
74
+
75
+ def timed_lru_cache(seconds: int = 300, maxsize: int = None):
76
+ def wrapper_cache(func):
77
+ func = lru_cache(maxsize=maxsize)(func)
78
+ func.delta = seconds * 10**9
79
+ func.expiration = monotonic_ns() + func.delta
80
+
81
+ @wraps(func)
82
+ def wrapped_func(*args, **kwargs):
83
+ if monotonic_ns() >= func.expiration:
84
+ func.cache_clear()
85
+ func.expiration = monotonic_ns() + func.delta
86
+ return func(*args, **kwargs)
87
+
88
+ return wrapped_func
89
+
90
+ return wrapper_cache
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: truefoundry
3
- Version: 0.3.0rc9
3
+ Version: 0.3.0rc11
4
4
  Summary: Truefoundry CLI
5
5
  Author: Abhishek Choudhary
6
6
  Author-email: abhishek@truefoundry.com
@@ -24,7 +24,7 @@ Requires-Dist: flytekit (==1.12.2) ; extra == "workflow"
24
24
  Requires-Dist: gitignorefile (>=1.1.2,<1.2.0)
25
25
  Requires-Dist: importlib-metadata (>=6.0.1,<8.0.0)
26
26
  Requires-Dist: importlib-resources (>=5.2.0,<6.0.0)
27
- Requires-Dist: mlfoundry (==0.11.2) ; extra == "ml"
27
+ Requires-Dist: mlfoundry (==0.11.4) ; extra == "ml"
28
28
  Requires-Dist: openai (>=1.16.2,<2.0.0)
29
29
  Requires-Dist: packaging (>=20.0,<25.0)
30
30
  Requires-Dist: pydantic (>=1.10.0,<3)
@@ -25,7 +25,7 @@ truefoundry/autodeploy/utils/diff.py,sha256=Ef8Y-VffDKel_-q-GxRam6gqiv8qTLMcqVg6
25
25
  truefoundry/autodeploy/utils/pydantic_compat.py,sha256=hEAUy5kLjhPdzw7yGZ2iXGMXbbMVXVlGzIofmyHafXQ,412
26
26
  truefoundry/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
27
27
  truefoundry/cli/__main__.py,sha256=Jap_IddZ9zNyMIyIkCw75xHQCN0WtV2dPZJ_pzdLsVc,916
28
- truefoundry/deploy/__init__.py,sha256=hyBoxhL3SG37vduJBdUYJuy1EHGeSLPI4S8MuKhyCFo,2259
28
+ truefoundry/deploy/__init__.py,sha256=ugawKF2G02EmEXX35oZ2tec12d9oWN28Sf6mtGGIERY,2281
29
29
  truefoundry/deploy/auto_gen/models.py,sha256=inof7aH6Wk1z15YYtCNJo7sp3Tixv5yaJzB_4fiZux4,78412
30
30
  truefoundry/deploy/builder/__init__.py,sha256=a1qR6nicHGcxRaeNTxWRsmDs8zsmXc7j13-I8q0qqVk,4938
31
31
  truefoundry/deploy/builder/builders/__init__.py,sha256=tlFLXqyDaKLd4iZbo4Hcu_8gOmgtL6drnXpbmQ6x1P8,636
@@ -36,7 +36,7 @@ truefoundry/deploy/builder/builders/tfy_python_buildpack/__init__.py,sha256=n7Mw
36
36
  truefoundry/deploy/builder/builders/tfy_python_buildpack/dockerfile_template.py,sha256=vFmFeK38-t8booJEGREapEjrIL8xnyOQeRSJQq7d3ZQ,6183
37
37
  truefoundry/deploy/builder/docker_service.py,sha256=vQS15790njzlFJZ3JW6txYLBdT11ltxqqpf78ZFL_Ng,5208
38
38
  truefoundry/deploy/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
39
- truefoundry/deploy/cli/cli.py,sha256=UM6nuyZJ1CfYmN8-A65GGDN3n3j0qmSZb283aMLIUOY,2649
39
+ truefoundry/deploy/cli/cli.py,sha256=l1vRYoovhx40HYZdfsC9JyiYzW9Jx6__7QDzQpN315I,2717
40
40
  truefoundry/deploy/cli/commands/__init__.py,sha256=oOstv608ueOJTxR3qlQbZBIdo-FsFe2O0NYNOXi01-s,1276
41
41
  truefoundry/deploy/cli/commands/apply_command.py,sha256=Xzky2csXwLARTpQBcPj87imnDu8tIDRN0GnqY8ebEuw,1863
42
42
  truefoundry/deploy/cli/commands/build_command.py,sha256=QwKkZ3nVecPMzs-R57YP-_ih9rjTSnhwBWX5tqHVsvU,1255
@@ -53,7 +53,7 @@ truefoundry/deploy/cli/commands/patch_application_command.py,sha256=Zuswj36o-qni
53
53
  truefoundry/deploy/cli/commands/patch_command.py,sha256=OQCmxcn1Qd2iZfBUaqs48oUKjHVZ13SoMsWLhksPvks,1682
54
54
  truefoundry/deploy/cli/commands/redeploy_command.py,sha256=-wMQLeMcBdJsQBMgTv7rS6hCqH1EJsSKgPrAXU9HjxU,1032
55
55
  truefoundry/deploy/cli/commands/terminate_comand.py,sha256=RTNuykw5DBvid44u2nCka_Eu0XSK3Qrzwob9fybHLgQ,1097
56
- truefoundry/deploy/cli/commands/trigger_command.py,sha256=TdGjhBFLlfVV7Ba044YsbFRSzDekSVEYdqoyLweJQdY,2748
56
+ truefoundry/deploy/cli/commands/trigger_command.py,sha256=Js6x7-TEuQQN1fTBoILTJiCt76TdH9qpAnkCnei6vYo,4730
57
57
  truefoundry/deploy/cli/config.py,sha256=tf8w4UfVzcC6eYkENvuuCPYt_V3sqVpO1bclORV9tAk,206
58
58
  truefoundry/deploy/cli/console.py,sha256=9-dMy4YPisCJQziRKTg8Qa0UJnOGl1soiUnJjsnLDvE,242
59
59
  truefoundry/deploy/cli/const.py,sha256=dVHPo1uAiDSSMXwXoT2mR5kNQjExT98QNVRz98Hz_Ts,510
@@ -78,17 +78,17 @@ truefoundry/deploy/io/output_callback.py,sha256=V2YwUFec4G4a67lM4r-x_64AqdOVNo_9
78
78
  truefoundry/deploy/io/rich_output_callback.py,sha256=TJLiRD-EnFVwgcepxR7WN0koKqW1X2DevETPhNPi_nU,829
79
79
  truefoundry/deploy/json_util.py,sha256=x_-7YYQ4_HUIJ8ofOcclAp9JWhgTWjR9Th6Q0FuRqGk,175
80
80
  truefoundry/deploy/lib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
81
- truefoundry/deploy/lib/auth/auth_service_client.py,sha256=rrz2t6lkNgVBoWsIrdyaK9OHN5XZJtA4AAqaDx3PQyc,3299
81
+ truefoundry/deploy/lib/auth/auth_service_client.py,sha256=Mzdl09CR8EHG5BA7vDTd0sOk2iStCgQeTIldjoCxyd0,7386
82
82
  truefoundry/deploy/lib/auth/credential_file_manager.py,sha256=DXeXWoVakfZI2Geu8Futwef_eVMHrZ1et7d9MIXOhhY,4233
83
- truefoundry/deploy/lib/auth/credential_provider.py,sha256=MwTN8170TXi7g9m2Fw4VRReZqk1DzBFG1bMVgd7jYZk,4375
83
+ truefoundry/deploy/lib/auth/credential_provider.py,sha256=eXgfA2-q20XxslOmlocmi-rKQ5AtBxVMGuftfrLVlb4,4403
84
84
  truefoundry/deploy/lib/auth/servicefoundry_session.py,sha256=2OahwRg-8l3QUwpC2iLA8lHavkeTxKXUP_0AN27HPS8,1859
85
85
  truefoundry/deploy/lib/clients/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
86
- truefoundry/deploy/lib/clients/servicefoundry_client.py,sha256=fq7kvQa2OgTs_TobCEPC_Yy0A-g0w7enOu0jdSfTyVc,26083
86
+ truefoundry/deploy/lib/clients/servicefoundry_client.py,sha256=yqeaF8nFeqR01q9d7E2s7sDQVpgF1ES9CECXpKNMT5g,26945
87
87
  truefoundry/deploy/lib/clients/shell_client.py,sha256=tMrc0Ha1DmGtUCJrZD8eusOzfe8R_WIe6AAH7nxL0xA,461
88
88
  truefoundry/deploy/lib/clients/utils.py,sha256=rK7DrvA71kSTjy23-Bk4LTQjgViBWeHtcV_SlBLZw6M,1282
89
89
  truefoundry/deploy/lib/const.py,sha256=Yk_nXeZWzwKs-6hEXDjVDyjwEGh35T5TWaBxyJgP-Zw,1395
90
90
  truefoundry/deploy/lib/dao/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
91
- truefoundry/deploy/lib/dao/application.py,sha256=I-4YicbU5tazo9JLkW9FlVpB-nRamdOliJNxApMaHJE,8419
91
+ truefoundry/deploy/lib/dao/application.py,sha256=uUTFSQkLUrFCtQQgS2Jm9BpyHyhMkN4GI1yx9oJo4_E,9161
92
92
  truefoundry/deploy/lib/dao/apply.py,sha256=sXnQY6RVzLVm1fX2BKuWHAoKlKISirrcByHEhY3x4zo,2570
93
93
  truefoundry/deploy/lib/dao/version.py,sha256=AtdW_4O1DPUKdfv2qy6iUJsZ_95vM6z0AqeEy3WDKs8,1130
94
94
  truefoundry/deploy/lib/dao/workspace.py,sha256=jm8UWytwVajVcrYyHSTCwWYDYl-RHuk0zAf9Caj4GzQ,2356
@@ -96,9 +96,9 @@ truefoundry/deploy/lib/exceptions.py,sha256=ZW44bSwmlcr3GcB10E8Jz-zlgu9wyi8tE7xA
96
96
  truefoundry/deploy/lib/logs_utils.py,sha256=SQxRv3jDDmgHdOUMhlMaAPGYskybnBUMpst7QU_i_sc,1469
97
97
  truefoundry/deploy/lib/messages.py,sha256=nhp0bCYf_XpUM68hTq5lBY-__vtEyV2uP7NgnJXJ_Vg,925
98
98
  truefoundry/deploy/lib/model/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
99
- truefoundry/deploy/lib/model/entity.py,sha256=gFlSG6RVuaWQQ2v3YtONhnTbIRzKUIryMgcJN6HmZV4,11309
100
- truefoundry/deploy/lib/session.py,sha256=0S9foO78BXYSwCh6nPaWG-QuwgxaK4VZqzshjNkyXls,5229
101
- truefoundry/deploy/lib/util.py,sha256=3Pc0gQgomapTSjMQo743STShBn1B6PNdBpw3bTpdxOw,2200
99
+ truefoundry/deploy/lib/model/entity.py,sha256=aNiQ7kK_V1kH7C_VC6HP7ibas_9Ohkoqzs-WdTfrrf4,12037
100
+ truefoundry/deploy/lib/session.py,sha256=WumH3cfVr8DqcuY5ngdnPBI_oeMUxG_JqyONQYKlM6k,5844
101
+ truefoundry/deploy/lib/util.py,sha256=sNMv9peDU7RTCDaAfyWPpPpCs_WcZGqOvc13Jqx9y6w,2809
102
102
  truefoundry/deploy/lib/win32.py,sha256=1RcvPTdlOAJ48rt8rCbE2Ufha2ztRqBAE9dueNXArrY,5009
103
103
  truefoundry/deploy/v2/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
104
104
  truefoundry/deploy/v2/lib/__init__.py,sha256=WEiVMZXOVljzEE3tpGJil14liIn_PCDoACJ6b3tZ6sI,188
@@ -130,7 +130,7 @@ truefoundry/workflow/map_task.py,sha256=2m3qGXQ90k9LdS45q8dqCCECc3qr8t2m_LMCVd1m
130
130
  truefoundry/workflow/python_task.py,sha256=SRXRLC4vdBqGjhkwuaY39LEWN6iPCpJAuW17URRdWTY,1128
131
131
  truefoundry/workflow/task.py,sha256=ToitYiKcNzFCtOVQwz1W8sRjbR97eVS7vQBdbgUQtKg,1779
132
132
  truefoundry/workflow/workflow.py,sha256=WaTqUjhwfAXDWu4E5ehuwAxrCbDJkoAf1oWmR2E9Qy0,4575
133
- truefoundry-0.3.0rc9.dist-info/METADATA,sha256=MoFxdl5KpAr9mCShojPeE2O2dXsgyB82DSjYKPIR9b0,2693
134
- truefoundry-0.3.0rc9.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
135
- truefoundry-0.3.0rc9.dist-info/entry_points.txt,sha256=TXvUxQkI6zmqJuycPsyxEIMr3oqfDjgrWj0m_9X12x4,95
136
- truefoundry-0.3.0rc9.dist-info/RECORD,,
133
+ truefoundry-0.3.0rc11.dist-info/METADATA,sha256=Qo4AmBpLd161EugnEW1A6n8e1S4jIZPJg3wyQEjvcio,2694
134
+ truefoundry-0.3.0rc11.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
135
+ truefoundry-0.3.0rc11.dist-info/entry_points.txt,sha256=TXvUxQkI6zmqJuycPsyxEIMr3oqfDjgrWj0m_9X12x4,95
136
+ truefoundry-0.3.0rc11.dist-info/RECORD,,