truefoundry 0.2.10__py3-none-any.whl → 0.3.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.

Files changed (112) hide show
  1. truefoundry/__init__.py +1 -0
  2. truefoundry/autodeploy/cli.py +31 -18
  3. truefoundry/deploy/__init__.py +112 -1
  4. truefoundry/deploy/auto_gen/models.py +1714 -0
  5. truefoundry/deploy/builder/__init__.py +134 -0
  6. truefoundry/deploy/builder/builders/__init__.py +22 -0
  7. truefoundry/deploy/builder/builders/dockerfile.py +57 -0
  8. truefoundry/deploy/builder/builders/tfy_notebook_buildpack/__init__.py +46 -0
  9. truefoundry/deploy/builder/builders/tfy_notebook_buildpack/dockerfile_template.py +66 -0
  10. truefoundry/deploy/builder/builders/tfy_python_buildpack/__init__.py +44 -0
  11. truefoundry/deploy/builder/builders/tfy_python_buildpack/dockerfile_template.py +158 -0
  12. truefoundry/deploy/builder/docker_service.py +168 -0
  13. truefoundry/deploy/cli/cli.py +21 -26
  14. truefoundry/deploy/cli/commands/__init__.py +18 -0
  15. truefoundry/deploy/cli/commands/apply_command.py +52 -0
  16. truefoundry/deploy/cli/commands/build_command.py +45 -0
  17. truefoundry/deploy/cli/commands/build_logs_command.py +89 -0
  18. truefoundry/deploy/cli/commands/create_command.py +75 -0
  19. truefoundry/deploy/cli/commands/delete_command.py +77 -0
  20. truefoundry/deploy/cli/commands/deploy_command.py +102 -0
  21. truefoundry/deploy/cli/commands/get_command.py +216 -0
  22. truefoundry/deploy/cli/commands/list_command.py +171 -0
  23. truefoundry/deploy/cli/commands/login_command.py +33 -0
  24. truefoundry/deploy/cli/commands/logout_command.py +20 -0
  25. truefoundry/deploy/cli/commands/logs_command.py +134 -0
  26. truefoundry/deploy/cli/commands/patch_application_command.py +81 -0
  27. truefoundry/deploy/cli/commands/patch_command.py +70 -0
  28. truefoundry/deploy/cli/commands/redeploy_command.py +41 -0
  29. truefoundry/deploy/cli/commands/terminate_comand.py +44 -0
  30. truefoundry/deploy/cli/commands/trigger_command.py +145 -0
  31. truefoundry/deploy/cli/config.py +10 -0
  32. truefoundry/deploy/cli/console.py +5 -0
  33. truefoundry/deploy/cli/const.py +12 -0
  34. truefoundry/deploy/cli/display_util.py +118 -0
  35. truefoundry/deploy/cli/util.py +129 -0
  36. truefoundry/deploy/core/__init__.py +7 -0
  37. truefoundry/deploy/core/login.py +9 -0
  38. truefoundry/deploy/core/logout.py +5 -0
  39. truefoundry/deploy/function_service/__init__.py +3 -0
  40. truefoundry/deploy/function_service/__main__.py +27 -0
  41. truefoundry/deploy/function_service/app.py +92 -0
  42. truefoundry/deploy/function_service/build.py +45 -0
  43. truefoundry/deploy/function_service/remote/__init__.py +6 -0
  44. truefoundry/deploy/function_service/remote/context.py +3 -0
  45. truefoundry/deploy/function_service/remote/method.py +67 -0
  46. truefoundry/deploy/function_service/remote/remote.py +144 -0
  47. truefoundry/deploy/function_service/route.py +137 -0
  48. truefoundry/deploy/function_service/service.py +113 -0
  49. truefoundry/deploy/function_service/utils.py +53 -0
  50. truefoundry/deploy/io/__init__.py +0 -0
  51. truefoundry/deploy/io/output_callback.py +23 -0
  52. truefoundry/deploy/io/rich_output_callback.py +27 -0
  53. truefoundry/deploy/json_util.py +7 -0
  54. truefoundry/deploy/lib/__init__.py +0 -0
  55. truefoundry/deploy/lib/auth/auth_service_client.py +181 -0
  56. truefoundry/deploy/lib/auth/credential_file_manager.py +115 -0
  57. truefoundry/deploy/lib/auth/credential_provider.py +131 -0
  58. truefoundry/deploy/lib/auth/servicefoundry_session.py +59 -0
  59. truefoundry/deploy/lib/clients/__init__.py +0 -0
  60. truefoundry/deploy/lib/clients/servicefoundry_client.py +746 -0
  61. truefoundry/deploy/lib/clients/shell_client.py +13 -0
  62. truefoundry/deploy/lib/clients/utils.py +41 -0
  63. truefoundry/deploy/lib/const.py +43 -0
  64. truefoundry/deploy/lib/dao/__init__.py +0 -0
  65. truefoundry/deploy/lib/dao/application.py +263 -0
  66. truefoundry/deploy/lib/dao/apply.py +80 -0
  67. truefoundry/deploy/lib/dao/version.py +33 -0
  68. truefoundry/deploy/lib/dao/workspace.py +71 -0
  69. truefoundry/deploy/lib/exceptions.py +26 -0
  70. truefoundry/deploy/lib/logs_utils.py +43 -0
  71. truefoundry/deploy/lib/messages.py +12 -0
  72. truefoundry/deploy/lib/model/__init__.py +0 -0
  73. truefoundry/deploy/lib/model/entity.py +400 -0
  74. truefoundry/deploy/lib/session.py +158 -0
  75. truefoundry/deploy/lib/util.py +90 -0
  76. truefoundry/deploy/lib/win32.py +129 -0
  77. truefoundry/deploy/v2/__init__.py +0 -0
  78. truefoundry/deploy/v2/lib/__init__.py +3 -0
  79. truefoundry/deploy/v2/lib/deploy.py +283 -0
  80. truefoundry/deploy/v2/lib/deploy_workflow.py +295 -0
  81. truefoundry/deploy/v2/lib/deployable_patched_models.py +86 -0
  82. truefoundry/deploy/v2/lib/models.py +53 -0
  83. truefoundry/deploy/v2/lib/patched_models.py +479 -0
  84. truefoundry/deploy/v2/lib/source.py +267 -0
  85. truefoundry/langchain/__init__.py +12 -1
  86. truefoundry/langchain/deprecated.py +302 -0
  87. truefoundry/langchain/truefoundry_chat.py +130 -0
  88. truefoundry/langchain/truefoundry_embeddings.py +171 -0
  89. truefoundry/langchain/truefoundry_llm.py +106 -0
  90. truefoundry/langchain/utils.py +85 -0
  91. truefoundry/logger.py +17 -0
  92. truefoundry/pydantic_v1.py +5 -0
  93. truefoundry/python_deploy_codegen.py +132 -0
  94. truefoundry/version.py +6 -0
  95. truefoundry/workflow/__init__.py +19 -0
  96. truefoundry/workflow/container_task.py +12 -0
  97. truefoundry/workflow/example/deploy.sh +1 -0
  98. truefoundry/workflow/example/hello_world_package/workflow.py +20 -0
  99. truefoundry/workflow/example/package/test_workflow.py +152 -0
  100. truefoundry/workflow/example/truefoundry.yaml +9 -0
  101. truefoundry/workflow/example/workflow.yaml +116 -0
  102. truefoundry/workflow/map_task.py +45 -0
  103. truefoundry/workflow/python_task.py +32 -0
  104. truefoundry/workflow/task.py +50 -0
  105. truefoundry/workflow/workflow.py +114 -0
  106. {truefoundry-0.2.10.dist-info → truefoundry-0.3.0.dist-info}/METADATA +27 -7
  107. truefoundry-0.3.0.dist-info/RECORD +136 -0
  108. truefoundry/deploy/cli/deploy.py +0 -165
  109. truefoundry/deploy/cli/version.py +0 -6
  110. truefoundry-0.2.10.dist-info/RECORD +0 -38
  111. {truefoundry-0.2.10.dist-info → truefoundry-0.3.0.dist-info}/WHEEL +0 -0
  112. {truefoundry-0.2.10.dist-info → truefoundry-0.3.0.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,70 @@
1
+ import subprocess
2
+ from typing import Optional
3
+
4
+ import rich_click as click
5
+
6
+ from truefoundry.deploy.cli.const import GROUP_CLS
7
+ from truefoundry.deploy.cli.util import handle_exception_wrapper
8
+ from truefoundry.deploy.io.rich_output_callback import RichOutputCallBack
9
+
10
+
11
+ @click.group(
12
+ name="patch",
13
+ cls=GROUP_CLS,
14
+ invoke_without_command=True,
15
+ help="Patch parts of servicefoundry.yaml file",
16
+ )
17
+ @click.option(
18
+ "-f",
19
+ "--file",
20
+ type=click.Path(exists=True, dir_okay=False, resolve_path=True),
21
+ default="./servicefoundry.yaml",
22
+ help="Path to servicefoundry.yaml file",
23
+ show_default=True,
24
+ )
25
+ @click.option(
26
+ "--filter",
27
+ type=click.STRING,
28
+ required=True,
29
+ help="`yq` filter",
30
+ )
31
+ @click.option(
32
+ "-o",
33
+ "--output-file",
34
+ type=click.Path(exists=False, writable=True, resolve_path=True),
35
+ help="Path to yaml file to redirect the output",
36
+ show_default=True,
37
+ )
38
+ @click.option(
39
+ "-I",
40
+ "--indent",
41
+ default=4,
42
+ type=click.INT,
43
+ help="Indent level for output",
44
+ show_default=True,
45
+ )
46
+ @handle_exception_wrapper
47
+ def patch_command(
48
+ file: str, filter: str, output_file: Optional[str], indent: int
49
+ ) -> None:
50
+ yq_command = [
51
+ "yq",
52
+ "--output-format",
53
+ "yaml",
54
+ "--indent",
55
+ str(indent),
56
+ filter,
57
+ file,
58
+ ]
59
+ if output_file:
60
+ with open(output_file, "w") as fd:
61
+ subprocess.run(yq_command, stdout=fd)
62
+ else:
63
+ p = subprocess.run(yq_command, stdout=subprocess.PIPE)
64
+ output = p.stdout.decode("UTF-8")
65
+ callback = RichOutputCallBack()
66
+ callback.print_line(output)
67
+
68
+
69
+ def get_patch_command():
70
+ return patch_command
@@ -0,0 +1,41 @@
1
+ import rich_click as click
2
+
3
+ from truefoundry.deploy.cli.const import COMMAND_CLS
4
+ from truefoundry.deploy.cli.util import handle_exception_wrapper
5
+ from truefoundry.deploy.lib.dao import application as application_lib
6
+
7
+
8
+ @click.command(name="redeploy", cls=COMMAND_CLS)
9
+ @click.option(
10
+ "--application-fqn",
11
+ type=click.STRING,
12
+ default=None,
13
+ help="Application fqn",
14
+ required=True,
15
+ )
16
+ @click.option(
17
+ "--version",
18
+ type=click.STRING,
19
+ default=None,
20
+ help="Application deployment version",
21
+ required=True,
22
+ )
23
+ @click.option(
24
+ "--wait/--no-wait",
25
+ is_flag=True,
26
+ show_default=True,
27
+ default=True,
28
+ help="wait and tail the deployment progress",
29
+ )
30
+ @handle_exception_wrapper
31
+ def redeploy_command(application_fqn: str, version: int, wait: bool):
32
+ """
33
+ Redeploy specific version of an application
34
+ """
35
+ _deployment = application_lib.redeploy_application(
36
+ application_fqn=application_fqn, version=version, wait=wait
37
+ )
38
+
39
+
40
+ def get_redeploy_command():
41
+ return redeploy_command
@@ -0,0 +1,44 @@
1
+ import rich_click as click
2
+
3
+ from truefoundry.deploy.cli.const import COMMAND_CLS, GROUP_CLS
4
+ from truefoundry.deploy.cli.display_util import print_json
5
+ from truefoundry.deploy.cli.util import handle_exception_wrapper
6
+ from truefoundry.deploy.lib.dao import application as application_lib
7
+
8
+
9
+ @click.group(name="terminate", cls=GROUP_CLS)
10
+ def terminate_command():
11
+ """
12
+ Terminate the job
13
+ """
14
+ pass
15
+
16
+
17
+ @click.command(name="job", cls=COMMAND_CLS, help="Terminate the Job")
18
+ @click.option(
19
+ "--job-fqn",
20
+ "--job_fqn",
21
+ type=click.STRING,
22
+ default=None,
23
+ help="FQN of the Job",
24
+ required=True,
25
+ )
26
+ @click.option(
27
+ "--job-run-name",
28
+ "--job_run_name",
29
+ type=click.STRING,
30
+ default=None,
31
+ help="Run name of the job",
32
+ required=True,
33
+ )
34
+ @handle_exception_wrapper
35
+ def terminate_job_run(job_fqn, job_run_name):
36
+ job_run = application_lib.terminate_job_run(
37
+ application_fqn=job_fqn, job_run_name=job_run_name
38
+ )
39
+ print_json(data=job_run)
40
+
41
+
42
+ def get_terminate_command():
43
+ terminate_command.add_command(terminate_job_run)
44
+ return terminate_command
@@ -0,0 +1,145 @@
1
+ from typing import Optional, Sequence
2
+
3
+ import rich_click as click
4
+ from click import ClickException
5
+
6
+ from truefoundry.deploy.cli.const import COMMAND_CLS, GROUP_CLS
7
+ from truefoundry.deploy.cli.util import handle_exception_wrapper
8
+ from truefoundry.deploy.lib.dao import application
9
+
10
+
11
+ @click.group(name="trigger", cls=GROUP_CLS)
12
+ def trigger_command():
13
+ """
14
+ Trigger a Job asynchronously
15
+ """
16
+ pass
17
+
18
+
19
+ @click.command(
20
+ name="job",
21
+ cls=COMMAND_CLS,
22
+ context_settings={"ignore_unknown_options": True, "allow_extra_args": True},
23
+ )
24
+ @click.option(
25
+ "--application-fqn",
26
+ "--application_fqn",
27
+ type=click.STRING,
28
+ required=True,
29
+ help="FQN of the deployment of the Job. This can be found on the Job details page.",
30
+ )
31
+ @click.option("--command", type=click.STRING, required=False, help="Command to run")
32
+ @click.argument(
33
+ "params",
34
+ type=click.STRING,
35
+ nargs=-1,
36
+ required=False,
37
+ )
38
+ @handle_exception_wrapper
39
+ def trigger_job(application_fqn: str, command: Optional[Sequence[str]], params):
40
+ """
41
+ Trigger a Job on TrueFoundry asynchronously
42
+
43
+ [b]tfy trigger job --application-fqn "my-cluster:my-workspace:my-job"[/]
44
+
45
+ \n
46
+ Additionally, you can either pass `--command` or params (if defined in the spec)\n
47
+
48
+
49
+ Passing a command:
50
+
51
+ [b]tfy trigger job --application-fqn "my-cluster:my-workspace:my-job" --command "python run.py"[/]
52
+ \n
53
+
54
+ Passing params:
55
+
56
+ [b]tfy trigger job --application-fqn "my-cluster:my-workspace:my-job" -- --param1_name param1_value --param2_name param2_value ...[/]
57
+ """
58
+ if params:
59
+ params_dict = {}
60
+ if len(params) % 2 != 0:
61
+ raise ClickException(
62
+ f"Found odd number of argument pairs: {params}. "
63
+ "Perhaps you forgot to pass a value for one of the params? "
64
+ "Job params should be passed in the "
65
+ "format `--param1_name param1_value --param2_name param2_value ...`"
66
+ )
67
+ for i in range(0, len(params), 2):
68
+ key = params[i]
69
+ value = params[i + 1]
70
+ if not key.startswith("--"):
71
+ raise ClickException(
72
+ f"Got ambiguous argument {key!r} in params: {params}. "
73
+ f"Param names should be prefixed with '--' i.e. "
74
+ "Job params should be passed in the "
75
+ "format `--param1_name param1_value --param2_name param2_value ...`"
76
+ )
77
+ key = key.lstrip("-")
78
+ params_dict[key] = value
79
+
80
+ application.trigger_job(
81
+ application_fqn=application_fqn, command=command, params=params
82
+ )
83
+
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
+
142
+ def get_trigger_command():
143
+ trigger_command.add_command(trigger_job)
144
+ trigger_command.add_command(trigger_workflow)
145
+ return trigger_command
@@ -0,0 +1,10 @@
1
+ class CliConfig:
2
+ __conf = {"json": False}
3
+
4
+ @staticmethod
5
+ def get(name):
6
+ return CliConfig.__conf[name]
7
+
8
+ @staticmethod
9
+ def set(name, value):
10
+ CliConfig.__conf[name] = value
@@ -0,0 +1,5 @@
1
+ from rich.console import Console
2
+
3
+ # TODO: this file should not exist here, it is being imported even outside cli
4
+ # moreover there is RichOutputCallBack now which can be used instead of console directly
5
+ console = Console(soft_wrap=True)
@@ -0,0 +1,12 @@
1
+ import os
2
+
3
+ import rich_click as click
4
+
5
+ DISPLAY_DATETIME_FORMAT = "%d %b %Y %H:%M:%S %Z"
6
+
7
+ # TODO (chiragjn): This is a hacky solution used while generating docs. Although
8
+ # this does not cover cases where custom cls class already inherited from rich_click classes
9
+ # is being used
10
+ RICH_CLICK_DISABLED = os.getenv("RICH_CLICK_DISABLED")
11
+ GROUP_CLS = click.Group if RICH_CLICK_DISABLED else click.RichGroup
12
+ COMMAND_CLS = click.Command if RICH_CLICK_DISABLED else click.RichCommand
@@ -0,0 +1,118 @@
1
+ import datetime
2
+ import json
3
+
4
+ from rich import box
5
+ from rich import print_json as _rich_print_json
6
+ from rich.table import Table
7
+
8
+ from truefoundry.deploy.cli.config import CliConfig
9
+ from truefoundry.deploy.cli.console import console
10
+ from truefoundry.deploy.cli.const import DISPLAY_DATETIME_FORMAT
11
+ from truefoundry.deploy.json_util import json_default_encoder
12
+
13
+
14
+ def print_json(data, default=json_default_encoder):
15
+ return _rich_print_json(
16
+ json.dumps(data, default=default), highlight=False, default=default
17
+ )
18
+
19
+
20
+ NO_WRAP_COLUMNS = {"fqn"}
21
+
22
+
23
+ def get_table(title):
24
+ return Table(title=title, show_lines=False, safe_box=True, box=box.MINIMAL)
25
+
26
+
27
+ def stringify(x):
28
+ if isinstance(x, datetime.datetime):
29
+ return x.astimezone().strftime(DISPLAY_DATETIME_FORMAT)
30
+ elif isinstance(x, str):
31
+ return x
32
+ else:
33
+ return str(x)
34
+
35
+
36
+ def display_time_passed(seconds: int):
37
+ m, s = divmod(seconds, 60)
38
+ h, m = divmod(m, 60)
39
+ d, h = divmod(h, 24)
40
+ result = ""
41
+ if d != 0:
42
+ result = f"{int(d)}D"
43
+ elif h != 0 and m != 0:
44
+ result = f"{int(h)}h {int(m)}m"
45
+ elif h != 0:
46
+ result = f"{int(h)}h"
47
+ elif m != 0 and s != 0:
48
+ result = f"{int(m)}m {int(s)}s"
49
+ elif m != 0:
50
+ result = f"{int(m)}m"
51
+ elif s != 0:
52
+ result = f"{int(s)}s"
53
+ return result
54
+
55
+
56
+ def print_entity_list(title, items):
57
+ items = [item.list_row_data() for item in items]
58
+ if CliConfig.get("json"):
59
+ print_json(data=items)
60
+ return
61
+
62
+ table = get_table(title)
63
+
64
+ columns = []
65
+ if items:
66
+ columns = items[0].keys()
67
+ for column in columns:
68
+ no_wrap = column in NO_WRAP_COLUMNS
69
+ table.add_column(column, justify="left", overflow="fold", no_wrap=no_wrap)
70
+
71
+ for item in items:
72
+ row = []
73
+ for c in columns:
74
+ row.append(stringify(item[c]))
75
+ table.add_row(*row)
76
+ console.print(table)
77
+
78
+
79
+ def print_obj(title, item, columns=None):
80
+ if CliConfig.get("json"):
81
+ print_json(data=item)
82
+ return
83
+
84
+ table = get_table(title)
85
+
86
+ if not columns:
87
+ columns = item.keys()
88
+
89
+ # transpose
90
+ keys, columns = columns, ["key", "value"]
91
+
92
+ for column in columns:
93
+ no_wrap = column in NO_WRAP_COLUMNS
94
+ table.add_column(column, justify="left", overflow="fold", no_wrap=no_wrap)
95
+ for key in keys:
96
+ table.add_row(f"[bold]{stringify(key)}[/]", stringify(item[key]))
97
+ console.print(table)
98
+
99
+
100
+ def print_entity_obj(title, entity):
101
+ if CliConfig.get("json"):
102
+ print_json(data=entity)
103
+ return
104
+
105
+ table = get_table(title)
106
+
107
+ columns = entity.get_data().keys()
108
+
109
+ # transpose
110
+ keys, columns = columns, ["key", "value"]
111
+
112
+ for column in columns:
113
+ no_wrap = "FQN" in column or "Name" in column
114
+ table.add_column(column, justify="left", overflow="fold", no_wrap=no_wrap)
115
+ entity_data = entity.get_data()
116
+ for key in keys:
117
+ table.add_row(f"[bold]{stringify(key)}[/]", stringify(entity_data[key]))
118
+ console.print(table)
@@ -0,0 +1,129 @@
1
+ import functools
2
+ import sys
3
+ import zipfile
4
+ from typing import Dict
5
+
6
+ import rich_click as click
7
+ from packaging.version import parse as parse_version
8
+ from requests.exceptions import ConnectionError
9
+ from rich.padding import Padding
10
+ from rich.panel import Panel
11
+ from rich.table import Table
12
+
13
+ from truefoundry.deploy.cli.console import console
14
+ from truefoundry.deploy.lib.exceptions import (
15
+ BadRequestException,
16
+ ConfigurationException,
17
+ )
18
+ from truefoundry.deploy.lib.util import is_debug_env_set
19
+
20
+
21
+ def setup_rich_click():
22
+ click.rich_click.STYLE_ERRORS_SUGGESTION = "blue italic"
23
+ click.rich_click.SHOW_ARGUMENTS = True
24
+ click.rich_click.USE_RICH_MARKUP = True
25
+ click.rich_click.STYLE_HELPTEXT = ""
26
+
27
+
28
+ def handle_exception(exception):
29
+ if is_debug_env_set():
30
+ console.print_exception(show_locals=True)
31
+ if isinstance(exception, BadRequestException):
32
+ print_dict_as_table_panel(
33
+ {"Status Code": str(exception.status_code), "Error": exception.message},
34
+ title="Command Failed",
35
+ border_style="red",
36
+ )
37
+ elif isinstance(exception, ConnectionError):
38
+ print_dict_as_table_panel(
39
+ {"Error": "Couldn't connect to TrueFoundry"},
40
+ title="Command Failed",
41
+ border_style="red",
42
+ )
43
+ elif isinstance(exception, ConfigurationException):
44
+ print_dict_as_table_panel(
45
+ {"Error": exception.message},
46
+ title="Command Failed",
47
+ border_style="red",
48
+ )
49
+ else:
50
+ print_dict_as_table_panel(
51
+ {"Error": str(exception)},
52
+ title="Command Failed",
53
+ border_style="red",
54
+ )
55
+
56
+
57
+ def handle_exception_wrapper(fn):
58
+ @functools.wraps(fn)
59
+ def inner(*args, **kwargs):
60
+ try:
61
+ return fn(*args, **kwargs)
62
+ except Exception as e:
63
+ handle_exception(e)
64
+ sys.exit(1)
65
+
66
+ return inner
67
+
68
+
69
+ def print_error(message):
70
+ text = Padding(message, (0, 1))
71
+ console.print(
72
+ Panel(
73
+ text,
74
+ border_style="red",
75
+ title="Command failed",
76
+ title_align="left",
77
+ width=click.rich_click.MAX_WIDTH,
78
+ )
79
+ )
80
+
81
+
82
+ def print_message(message):
83
+ text = Padding(message, (0, 1))
84
+ console.print(
85
+ Panel(
86
+ text,
87
+ border_style="cyan",
88
+ title="Success",
89
+ title_align="left",
90
+ width=click.rich_click.MAX_WIDTH,
91
+ )
92
+ )
93
+
94
+
95
+ def print_dict_as_table_panel(
96
+ dct: Dict[str, str],
97
+ title: str,
98
+ border_style: str = "cyan",
99
+ key_color: str = "cyan",
100
+ ):
101
+ table = Table(show_header=False, box=None)
102
+ table.add_column("Key", style=f"bold {key_color}", width=15)
103
+ table.add_column("Value")
104
+ for key, value in dct.items():
105
+ table.add_row(key, value)
106
+ console.print(
107
+ Panel(
108
+ table,
109
+ border_style=border_style,
110
+ title=title,
111
+ title_align="left",
112
+ width=click.rich_click.MAX_WIDTH,
113
+ )
114
+ )
115
+
116
+
117
+ def unzip_package(path_to_package, destination):
118
+ with zipfile.ZipFile(path_to_package, "r") as zip_ref:
119
+ zip_ref.extractall(destination)
120
+
121
+
122
+ def _prompt_if_no_value_and_supported(prompt: str, hide_input: bool = True):
123
+ import click as _click
124
+
125
+ kwargs = {}
126
+ if parse_version(_click.__version__).major >= 8:
127
+ kwargs = {"prompt": prompt, "hide_input": hide_input, "prompt_required": False}
128
+
129
+ return kwargs
@@ -0,0 +1,7 @@
1
+ from truefoundry.deploy.core.login import login
2
+ from truefoundry.deploy.core.logout import logout
3
+
4
+ __all__ = [
5
+ "login",
6
+ "logout",
7
+ ]
@@ -0,0 +1,9 @@
1
+ from typing import Optional
2
+
3
+ from truefoundry.deploy.lib import session
4
+
5
+
6
+ def login(
7
+ host: Optional[str] = None, api_key: Optional[str] = None, relogin: bool = False
8
+ ):
9
+ session.login(api_key=api_key, relogin=relogin, host=host)
@@ -0,0 +1,5 @@
1
+ from truefoundry.deploy.lib import session
2
+
3
+
4
+ def logout():
5
+ session.logout()
@@ -0,0 +1,3 @@
1
+ from truefoundry.deploy.function_service.build import BuildConfig
2
+ from truefoundry.deploy.function_service.remote import remote
3
+ from truefoundry.deploy.function_service.service import FunctionService
@@ -0,0 +1,27 @@
1
+ import json
2
+
3
+ import click
4
+
5
+ from truefoundry.deploy.function_service.app import build_and_run_app
6
+ from truefoundry.deploy.function_service.route import RouteGroups
7
+
8
+
9
+ ####
10
+ # I am keeping the CLI here for now. This will get refactored going forward.
11
+ @click.group()
12
+ def cli():
13
+ pass
14
+
15
+
16
+ # python -m truefoundry.deploy.function_service run --port 8000 --route-group-json ""
17
+ # I am going to use this as "CMD" in the dockerfile to bring up the service
18
+ @cli.command()
19
+ @click.option("--route-groups-json", required=True, type=str)
20
+ @click.option("--port", required=True, type=int)
21
+ def run(port: int, route_groups_json: str):
22
+ route_groups = RouteGroups.parse_obj(json.loads(route_groups_json))
23
+ build_and_run_app(route_groups=route_groups, port=port)
24
+
25
+
26
+ if __name__ == "__main__":
27
+ cli()