flyte 0.2.0b1__py3-none-any.whl → 2.0.0b46__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.
- flyte/__init__.py +83 -30
- flyte/_bin/connect.py +61 -0
- flyte/_bin/debug.py +38 -0
- flyte/_bin/runtime.py +87 -19
- flyte/_bin/serve.py +351 -0
- flyte/_build.py +3 -2
- flyte/_cache/cache.py +6 -5
- flyte/_cache/local_cache.py +216 -0
- flyte/_code_bundle/_ignore.py +31 -5
- flyte/_code_bundle/_packaging.py +42 -11
- flyte/_code_bundle/_utils.py +57 -34
- flyte/_code_bundle/bundle.py +130 -27
- flyte/_constants.py +1 -0
- flyte/_context.py +21 -5
- flyte/_custom_context.py +73 -0
- flyte/_debug/constants.py +37 -0
- flyte/_debug/utils.py +17 -0
- flyte/_debug/vscode.py +315 -0
- flyte/_deploy.py +396 -75
- flyte/_deployer.py +109 -0
- flyte/_environment.py +94 -11
- flyte/_excepthook.py +37 -0
- flyte/_group.py +2 -1
- flyte/_hash.py +1 -16
- flyte/_image.py +544 -231
- flyte/_initialize.py +456 -316
- flyte/_interface.py +40 -5
- flyte/_internal/controllers/__init__.py +22 -8
- flyte/_internal/controllers/_local_controller.py +159 -35
- flyte/_internal/controllers/_trace.py +18 -10
- flyte/_internal/controllers/remote/__init__.py +38 -9
- flyte/_internal/controllers/remote/_action.py +82 -12
- flyte/_internal/controllers/remote/_client.py +6 -2
- flyte/_internal/controllers/remote/_controller.py +290 -64
- flyte/_internal/controllers/remote/_core.py +155 -95
- flyte/_internal/controllers/remote/_informer.py +40 -20
- flyte/_internal/controllers/remote/_service_protocol.py +2 -2
- flyte/_internal/imagebuild/__init__.py +2 -10
- flyte/_internal/imagebuild/docker_builder.py +391 -84
- flyte/_internal/imagebuild/image_builder.py +111 -55
- flyte/_internal/imagebuild/remote_builder.py +409 -0
- flyte/_internal/imagebuild/utils.py +79 -0
- flyte/_internal/resolvers/_app_env_module.py +92 -0
- flyte/_internal/resolvers/_task_module.py +5 -38
- flyte/_internal/resolvers/app_env.py +26 -0
- flyte/_internal/resolvers/common.py +8 -1
- flyte/_internal/resolvers/default.py +2 -2
- flyte/_internal/runtime/convert.py +319 -36
- flyte/_internal/runtime/entrypoints.py +106 -18
- flyte/_internal/runtime/io.py +71 -23
- flyte/_internal/runtime/resources_serde.py +21 -7
- flyte/_internal/runtime/reuse.py +125 -0
- flyte/_internal/runtime/rusty.py +196 -0
- flyte/_internal/runtime/task_serde.py +239 -66
- flyte/_internal/runtime/taskrunner.py +48 -8
- flyte/_internal/runtime/trigger_serde.py +162 -0
- flyte/_internal/runtime/types_serde.py +7 -16
- flyte/_keyring/file.py +115 -0
- flyte/_link.py +30 -0
- flyte/_logging.py +241 -42
- flyte/_map.py +312 -0
- flyte/_metrics.py +59 -0
- flyte/_module.py +74 -0
- flyte/_pod.py +30 -0
- flyte/_resources.py +296 -33
- flyte/_retry.py +1 -7
- flyte/_reusable_environment.py +72 -7
- flyte/_run.py +462 -132
- flyte/_secret.py +47 -11
- flyte/_serve.py +333 -0
- flyte/_task.py +245 -56
- flyte/_task_environment.py +219 -97
- flyte/_task_plugins.py +47 -0
- flyte/_tools.py +8 -8
- flyte/_trace.py +15 -24
- flyte/_trigger.py +1027 -0
- flyte/_utils/__init__.py +12 -1
- flyte/_utils/asyn.py +3 -1
- flyte/_utils/async_cache.py +139 -0
- flyte/_utils/coro_management.py +5 -4
- flyte/_utils/description_parser.py +19 -0
- flyte/_utils/docker_credentials.py +173 -0
- flyte/_utils/helpers.py +45 -19
- flyte/_utils/module_loader.py +123 -0
- flyte/_utils/org_discovery.py +57 -0
- flyte/_utils/uv_script_parser.py +8 -1
- flyte/_version.py +16 -3
- flyte/app/__init__.py +27 -0
- flyte/app/_app_environment.py +362 -0
- flyte/app/_connector_environment.py +40 -0
- flyte/app/_deploy.py +130 -0
- flyte/app/_parameter.py +343 -0
- flyte/app/_runtime/__init__.py +3 -0
- flyte/app/_runtime/app_serde.py +383 -0
- flyte/app/_types.py +113 -0
- flyte/app/extras/__init__.py +9 -0
- flyte/app/extras/_auth_middleware.py +217 -0
- flyte/app/extras/_fastapi.py +93 -0
- flyte/app/extras/_model_loader/__init__.py +3 -0
- flyte/app/extras/_model_loader/config.py +7 -0
- flyte/app/extras/_model_loader/loader.py +288 -0
- flyte/cli/__init__.py +12 -0
- flyte/cli/_abort.py +28 -0
- flyte/cli/_build.py +114 -0
- flyte/cli/_common.py +493 -0
- flyte/cli/_create.py +371 -0
- flyte/cli/_delete.py +45 -0
- flyte/cli/_deploy.py +401 -0
- flyte/cli/_gen.py +316 -0
- flyte/cli/_get.py +446 -0
- flyte/cli/_option.py +33 -0
- flyte/{_cli → cli}/_params.py +57 -17
- flyte/cli/_plugins.py +209 -0
- flyte/cli/_prefetch.py +292 -0
- flyte/cli/_run.py +690 -0
- flyte/cli/_serve.py +338 -0
- flyte/cli/_update.py +86 -0
- flyte/cli/_user.py +20 -0
- flyte/cli/main.py +246 -0
- flyte/config/__init__.py +2 -167
- flyte/config/_config.py +215 -163
- flyte/config/_internal.py +10 -1
- flyte/config/_reader.py +225 -0
- flyte/connectors/__init__.py +11 -0
- flyte/connectors/_connector.py +330 -0
- flyte/connectors/_server.py +194 -0
- flyte/connectors/utils.py +159 -0
- flyte/errors.py +134 -2
- flyte/extend.py +24 -0
- flyte/extras/_container.py +69 -56
- flyte/git/__init__.py +3 -0
- flyte/git/_config.py +279 -0
- flyte/io/__init__.py +8 -1
- flyte/io/{structured_dataset → _dataframe}/__init__.py +32 -30
- flyte/io/{structured_dataset → _dataframe}/basic_dfs.py +75 -68
- flyte/io/{structured_dataset/structured_dataset.py → _dataframe/dataframe.py} +207 -242
- flyte/io/_dir.py +575 -113
- flyte/io/_file.py +587 -141
- flyte/io/_hashing_io.py +342 -0
- flyte/io/extend.py +7 -0
- flyte/models.py +635 -0
- flyte/prefetch/__init__.py +22 -0
- flyte/prefetch/_hf_model.py +563 -0
- flyte/remote/__init__.py +14 -3
- flyte/remote/_action.py +879 -0
- flyte/remote/_app.py +346 -0
- flyte/remote/_auth_metadata.py +42 -0
- flyte/remote/_client/_protocols.py +62 -4
- flyte/remote/_client/auth/_auth_utils.py +19 -0
- flyte/remote/_client/auth/_authenticators/base.py +8 -2
- flyte/remote/_client/auth/_authenticators/device_code.py +4 -5
- flyte/remote/_client/auth/_authenticators/factory.py +4 -0
- flyte/remote/_client/auth/_authenticators/passthrough.py +79 -0
- flyte/remote/_client/auth/_authenticators/pkce.py +17 -18
- flyte/remote/_client/auth/_channel.py +47 -18
- flyte/remote/_client/auth/_client_config.py +5 -3
- flyte/remote/_client/auth/_keyring.py +15 -2
- flyte/remote/_client/auth/_token_client.py +3 -3
- flyte/remote/_client/controlplane.py +206 -18
- flyte/remote/_common.py +66 -0
- flyte/remote/_data.py +107 -22
- flyte/remote/_logs.py +116 -33
- flyte/remote/_project.py +21 -19
- flyte/remote/_run.py +164 -631
- flyte/remote/_secret.py +72 -29
- flyte/remote/_task.py +387 -46
- flyte/remote/_trigger.py +368 -0
- flyte/remote/_user.py +43 -0
- flyte/report/_report.py +10 -6
- flyte/storage/__init__.py +13 -1
- flyte/storage/_config.py +237 -0
- flyte/storage/_parallel_reader.py +289 -0
- flyte/storage/_storage.py +268 -59
- flyte/syncify/__init__.py +56 -0
- flyte/syncify/_api.py +414 -0
- flyte/types/__init__.py +39 -0
- flyte/types/_interface.py +22 -7
- flyte/{io/pickle/transformer.py → types/_pickle.py} +37 -9
- flyte/types/_string_literals.py +8 -9
- flyte/types/_type_engine.py +226 -126
- flyte/types/_utils.py +1 -1
- flyte-2.0.0b46.data/scripts/debug.py +38 -0
- flyte-2.0.0b46.data/scripts/runtime.py +194 -0
- flyte-2.0.0b46.dist-info/METADATA +352 -0
- flyte-2.0.0b46.dist-info/RECORD +221 -0
- flyte-2.0.0b46.dist-info/entry_points.txt +8 -0
- flyte-2.0.0b46.dist-info/licenses/LICENSE +201 -0
- flyte/_api_commons.py +0 -3
- flyte/_cli/_common.py +0 -299
- flyte/_cli/_create.py +0 -42
- flyte/_cli/_delete.py +0 -23
- flyte/_cli/_deploy.py +0 -140
- flyte/_cli/_get.py +0 -235
- flyte/_cli/_run.py +0 -174
- flyte/_cli/main.py +0 -98
- flyte/_datastructures.py +0 -342
- flyte/_internal/controllers/pbhash.py +0 -39
- flyte/_protos/common/authorization_pb2.py +0 -66
- flyte/_protos/common/authorization_pb2.pyi +0 -108
- flyte/_protos/common/authorization_pb2_grpc.py +0 -4
- flyte/_protos/common/identifier_pb2.py +0 -71
- flyte/_protos/common/identifier_pb2.pyi +0 -82
- flyte/_protos/common/identifier_pb2_grpc.py +0 -4
- flyte/_protos/common/identity_pb2.py +0 -48
- flyte/_protos/common/identity_pb2.pyi +0 -72
- flyte/_protos/common/identity_pb2_grpc.py +0 -4
- flyte/_protos/common/list_pb2.py +0 -36
- flyte/_protos/common/list_pb2.pyi +0 -69
- flyte/_protos/common/list_pb2_grpc.py +0 -4
- flyte/_protos/common/policy_pb2.py +0 -37
- flyte/_protos/common/policy_pb2.pyi +0 -27
- flyte/_protos/common/policy_pb2_grpc.py +0 -4
- flyte/_protos/common/role_pb2.py +0 -37
- flyte/_protos/common/role_pb2.pyi +0 -53
- flyte/_protos/common/role_pb2_grpc.py +0 -4
- flyte/_protos/common/runtime_version_pb2.py +0 -28
- flyte/_protos/common/runtime_version_pb2.pyi +0 -24
- flyte/_protos/common/runtime_version_pb2_grpc.py +0 -4
- flyte/_protos/logs/dataplane/payload_pb2.py +0 -96
- flyte/_protos/logs/dataplane/payload_pb2.pyi +0 -168
- flyte/_protos/logs/dataplane/payload_pb2_grpc.py +0 -4
- flyte/_protos/secret/definition_pb2.py +0 -49
- flyte/_protos/secret/definition_pb2.pyi +0 -93
- flyte/_protos/secret/definition_pb2_grpc.py +0 -4
- flyte/_protos/secret/payload_pb2.py +0 -62
- flyte/_protos/secret/payload_pb2.pyi +0 -94
- flyte/_protos/secret/payload_pb2_grpc.py +0 -4
- flyte/_protos/secret/secret_pb2.py +0 -38
- flyte/_protos/secret/secret_pb2.pyi +0 -6
- flyte/_protos/secret/secret_pb2_grpc.py +0 -198
- flyte/_protos/secret/secret_pb2_grpc_grpc.py +0 -198
- flyte/_protos/validate/validate/validate_pb2.py +0 -76
- flyte/_protos/workflow/node_execution_service_pb2.py +0 -26
- flyte/_protos/workflow/node_execution_service_pb2.pyi +0 -4
- flyte/_protos/workflow/node_execution_service_pb2_grpc.py +0 -32
- flyte/_protos/workflow/queue_service_pb2.py +0 -106
- flyte/_protos/workflow/queue_service_pb2.pyi +0 -141
- flyte/_protos/workflow/queue_service_pb2_grpc.py +0 -172
- flyte/_protos/workflow/run_definition_pb2.py +0 -128
- flyte/_protos/workflow/run_definition_pb2.pyi +0 -310
- flyte/_protos/workflow/run_definition_pb2_grpc.py +0 -4
- flyte/_protos/workflow/run_logs_service_pb2.py +0 -41
- flyte/_protos/workflow/run_logs_service_pb2.pyi +0 -28
- flyte/_protos/workflow/run_logs_service_pb2_grpc.py +0 -69
- flyte/_protos/workflow/run_service_pb2.py +0 -133
- flyte/_protos/workflow/run_service_pb2.pyi +0 -175
- flyte/_protos/workflow/run_service_pb2_grpc.py +0 -412
- flyte/_protos/workflow/state_service_pb2.py +0 -58
- flyte/_protos/workflow/state_service_pb2.pyi +0 -71
- flyte/_protos/workflow/state_service_pb2_grpc.py +0 -138
- flyte/_protos/workflow/task_definition_pb2.py +0 -72
- flyte/_protos/workflow/task_definition_pb2.pyi +0 -65
- flyte/_protos/workflow/task_definition_pb2_grpc.py +0 -4
- flyte/_protos/workflow/task_service_pb2.py +0 -44
- flyte/_protos/workflow/task_service_pb2.pyi +0 -31
- flyte/_protos/workflow/task_service_pb2_grpc.py +0 -104
- flyte/io/_dataframe.py +0 -0
- flyte/io/pickle/__init__.py +0 -0
- flyte/remote/_console.py +0 -18
- flyte-0.2.0b1.dist-info/METADATA +0 -179
- flyte-0.2.0b1.dist-info/RECORD +0 -204
- flyte-0.2.0b1.dist-info/entry_points.txt +0 -3
- /flyte/{_cli → _debug}/__init__.py +0 -0
- /flyte/{_protos → _keyring}/__init__.py +0 -0
- {flyte-0.2.0b1.dist-info → flyte-2.0.0b46.dist-info}/WHEEL +0 -0
- {flyte-0.2.0b1.dist-info → flyte-2.0.0b46.dist-info}/top_level.txt +0 -0
flyte/cli/_gen.py
ADDED
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
import textwrap
|
|
2
|
+
from os import getcwd
|
|
3
|
+
from typing import Generator, Tuple
|
|
4
|
+
|
|
5
|
+
import rich_click as click
|
|
6
|
+
|
|
7
|
+
import flyte.cli._common as common
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@click.group(name="gen")
|
|
11
|
+
def gen():
|
|
12
|
+
"""
|
|
13
|
+
Generate documentation.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@gen.command(cls=common.CommandBase)
|
|
18
|
+
@click.option("--type", "doc_type", type=str, required=True, help="Type of documentation (valid: markdown)")
|
|
19
|
+
@click.pass_obj
|
|
20
|
+
def docs(cfg: common.CLIConfig, doc_type: str, project: str | None = None, domain: str | None = None):
|
|
21
|
+
"""
|
|
22
|
+
Generate documentation.
|
|
23
|
+
"""
|
|
24
|
+
if doc_type == "markdown":
|
|
25
|
+
markdown(cfg)
|
|
26
|
+
else:
|
|
27
|
+
raise click.ClickException("Invalid documentation type: {}".format(doc_type))
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def walk_commands(ctx: click.Context) -> Generator[Tuple[str, click.Command, click.Context], None, None]:
|
|
31
|
+
"""
|
|
32
|
+
Recursively walk a Click command tree, starting from the given context.
|
|
33
|
+
|
|
34
|
+
Yields:
|
|
35
|
+
(full_command_path, command_object, context)
|
|
36
|
+
"""
|
|
37
|
+
command = ctx.command
|
|
38
|
+
|
|
39
|
+
if not isinstance(command, click.Group):
|
|
40
|
+
yield ctx.command_path, command, ctx
|
|
41
|
+
elif isinstance(command, common.FileGroup):
|
|
42
|
+
# If the command is a FileGroup, yield its file path and the command itself
|
|
43
|
+
# No need to recurse further into FileGroup as most subcommands are dynamically generated
|
|
44
|
+
# The exception is TaskFiles which has the special 'deployed-task' subcommand that should be documented
|
|
45
|
+
if type(command).__name__ == "TaskFiles":
|
|
46
|
+
# For TaskFiles, we only want the special non-file-based subcommands like 'deployed-task'
|
|
47
|
+
# Exclude all dynamic file-based commands
|
|
48
|
+
try:
|
|
49
|
+
names = command.list_commands(ctx)
|
|
50
|
+
for name in names:
|
|
51
|
+
if name == "deployed-task": # Only include the deployed-task command
|
|
52
|
+
try:
|
|
53
|
+
subcommand = command.get_command(ctx, name)
|
|
54
|
+
if subcommand is not None:
|
|
55
|
+
full_name = f"{ctx.command_path} {name}".strip()
|
|
56
|
+
sub_ctx = click.Context(subcommand, info_name=name, parent=ctx)
|
|
57
|
+
yield full_name, subcommand, sub_ctx
|
|
58
|
+
except click.ClickException:
|
|
59
|
+
continue
|
|
60
|
+
except click.ClickException:
|
|
61
|
+
pass
|
|
62
|
+
|
|
63
|
+
yield ctx.command_path, command, ctx
|
|
64
|
+
else:
|
|
65
|
+
try:
|
|
66
|
+
names = command.list_commands(ctx)
|
|
67
|
+
except click.ClickException:
|
|
68
|
+
# Some file-based commands might not have valid objects (e.g., test files)
|
|
69
|
+
# Skip these gracefully
|
|
70
|
+
return
|
|
71
|
+
|
|
72
|
+
for name in names:
|
|
73
|
+
try:
|
|
74
|
+
subcommand = command.get_command(ctx, name)
|
|
75
|
+
if subcommand is None:
|
|
76
|
+
continue
|
|
77
|
+
|
|
78
|
+
full_name = f"{ctx.command_path} {name}".strip()
|
|
79
|
+
sub_ctx = click.Context(subcommand, info_name=name, parent=ctx)
|
|
80
|
+
yield full_name, subcommand, sub_ctx
|
|
81
|
+
|
|
82
|
+
# Recurse if subcommand is a MultiCommand (i.e., has its own subcommands)
|
|
83
|
+
# But skip RemoteTaskGroup as it requires a live Flyte backend to enumerate subcommands
|
|
84
|
+
if isinstance(subcommand, click.Group) and type(subcommand).__name__ != "RemoteTaskGroup":
|
|
85
|
+
yield from walk_commands(sub_ctx)
|
|
86
|
+
except click.ClickException:
|
|
87
|
+
# Skip files/commands that can't be loaded
|
|
88
|
+
continue
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def get_plugin_info(cmd: click.Command) -> tuple[bool, str | None]:
|
|
92
|
+
"""
|
|
93
|
+
Determine if a command is from a plugin and get the plugin module name.
|
|
94
|
+
|
|
95
|
+
Returns:
|
|
96
|
+
(is_plugin, plugin_module_name)
|
|
97
|
+
"""
|
|
98
|
+
if not cmd or not cmd.callback:
|
|
99
|
+
return False, None
|
|
100
|
+
|
|
101
|
+
module = cmd.callback.__module__
|
|
102
|
+
if "flyte." not in module:
|
|
103
|
+
# External plugin
|
|
104
|
+
parts = module.split(".")
|
|
105
|
+
if len(parts) == 1:
|
|
106
|
+
return True, parts[0]
|
|
107
|
+
return True, f"{parts[0]}.{parts[1]}"
|
|
108
|
+
elif module.startswith("flyte.") and not module.startswith("flyte.cli"):
|
|
109
|
+
# Check if it's from a flyte plugin (not core CLI)
|
|
110
|
+
# Core CLI modules are: flyte.cli.*
|
|
111
|
+
# Plugin modules would be things like: flyte.databricks, flyte.snowflake, etc.
|
|
112
|
+
parts = module.split(".")
|
|
113
|
+
if len(parts) > 1 and parts[1] not in ["cli", "remote", "core", "internal", "app"]:
|
|
114
|
+
return True, f"flyte.{parts[1]}"
|
|
115
|
+
|
|
116
|
+
return False, None
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def markdown(cfg: common.CLIConfig):
|
|
120
|
+
"""
|
|
121
|
+
Generate documentation in Markdown format
|
|
122
|
+
"""
|
|
123
|
+
ctx = cfg.ctx
|
|
124
|
+
|
|
125
|
+
output = []
|
|
126
|
+
# Store verbs with their nouns: {verb_name: [(noun_name, is_plugin, plugin_module), ...]}
|
|
127
|
+
output_verb_groups: dict[str, list[tuple[str, bool, str | None]]] = {}
|
|
128
|
+
# Store verb metadata: {verb_name: (is_plugin, plugin_module)}
|
|
129
|
+
verb_metadata: dict[str, tuple[bool, str | None]] = {}
|
|
130
|
+
# Store nouns with their verbs: {noun_name: [(verb_name, is_plugin, plugin_module), ...]}
|
|
131
|
+
output_noun_groups: dict[str, list[tuple[str, bool, str | None]]] = {}
|
|
132
|
+
|
|
133
|
+
processed = []
|
|
134
|
+
commands = [*[("flyte", ctx.command, ctx)], *walk_commands(ctx)]
|
|
135
|
+
for cmd_path, cmd, cmd_ctx in commands:
|
|
136
|
+
if cmd in processed:
|
|
137
|
+
# We already processed this command, skip it
|
|
138
|
+
continue
|
|
139
|
+
processed.append(cmd)
|
|
140
|
+
output.append("")
|
|
141
|
+
|
|
142
|
+
is_plugin, plugin_module = get_plugin_info(cmd)
|
|
143
|
+
|
|
144
|
+
cmd_path_parts = cmd_path.split(" ")
|
|
145
|
+
|
|
146
|
+
if len(cmd_path_parts) > 1:
|
|
147
|
+
verb = cmd_path_parts[1]
|
|
148
|
+
|
|
149
|
+
# Store verb metadata
|
|
150
|
+
if verb not in verb_metadata:
|
|
151
|
+
verb_metadata[verb] = (is_plugin, plugin_module)
|
|
152
|
+
|
|
153
|
+
# Initialize verb group if needed
|
|
154
|
+
if verb not in output_verb_groups:
|
|
155
|
+
output_verb_groups[verb] = []
|
|
156
|
+
|
|
157
|
+
if len(cmd_path_parts) > 2:
|
|
158
|
+
noun = cmd_path_parts[2]
|
|
159
|
+
# Add noun to verb's list
|
|
160
|
+
output_verb_groups[verb].append((noun, is_plugin, plugin_module))
|
|
161
|
+
|
|
162
|
+
if len(cmd_path_parts) == 3:
|
|
163
|
+
noun = cmd_path_parts[2]
|
|
164
|
+
verb = cmd_path_parts[1]
|
|
165
|
+
if noun not in output_noun_groups:
|
|
166
|
+
output_noun_groups[noun] = []
|
|
167
|
+
output_noun_groups[noun].append((verb, is_plugin, plugin_module))
|
|
168
|
+
|
|
169
|
+
output.append(f"{'#' * (len(cmd_path_parts) + 1)} {cmd_path}")
|
|
170
|
+
|
|
171
|
+
# Add plugin notice if this is a plugin command
|
|
172
|
+
if is_plugin and plugin_module:
|
|
173
|
+
output.append("")
|
|
174
|
+
output.append(
|
|
175
|
+
f"> **Note:** This command is provided by the `{plugin_module}` plugin. "
|
|
176
|
+
f"See the plugin documentation for installation instructions."
|
|
177
|
+
)
|
|
178
|
+
|
|
179
|
+
# Add usage information
|
|
180
|
+
output.append("")
|
|
181
|
+
usage_line = f"{cmd_path}"
|
|
182
|
+
|
|
183
|
+
# Add [OPTIONS] if command has options
|
|
184
|
+
if any(isinstance(p, click.Option) for p in cmd.params):
|
|
185
|
+
usage_line += " [OPTIONS]"
|
|
186
|
+
|
|
187
|
+
# Add command-specific usage pattern
|
|
188
|
+
if isinstance(cmd, click.Group):
|
|
189
|
+
usage_line += " COMMAND [ARGS]..."
|
|
190
|
+
else:
|
|
191
|
+
# Add arguments if any
|
|
192
|
+
args = [p for p in cmd.params if isinstance(p, click.Argument)]
|
|
193
|
+
for arg in args:
|
|
194
|
+
if arg.name: # Check if name is not None
|
|
195
|
+
if arg.required:
|
|
196
|
+
usage_line += f" {arg.name.upper()}"
|
|
197
|
+
else:
|
|
198
|
+
usage_line += f" [{arg.name.upper()}]"
|
|
199
|
+
|
|
200
|
+
output.append(f"**`{usage_line}`**")
|
|
201
|
+
|
|
202
|
+
if cmd.help:
|
|
203
|
+
output.append("")
|
|
204
|
+
output.append(f"{dedent(cmd.help)}")
|
|
205
|
+
|
|
206
|
+
if not cmd.params:
|
|
207
|
+
continue
|
|
208
|
+
|
|
209
|
+
params = cmd.get_params(cmd_ctx)
|
|
210
|
+
|
|
211
|
+
# Collect all data first to calculate column widths
|
|
212
|
+
table_data = []
|
|
213
|
+
for param in params:
|
|
214
|
+
if isinstance(param, click.Option):
|
|
215
|
+
# Format each option with backticks before joining
|
|
216
|
+
all_opts = param.opts + param.secondary_opts
|
|
217
|
+
if len(all_opts) == 1:
|
|
218
|
+
opts = f"`{all_opts[0]}`"
|
|
219
|
+
else:
|
|
220
|
+
opts = "".join(
|
|
221
|
+
[
|
|
222
|
+
"{{< multiline >}}",
|
|
223
|
+
"\n".join([f"`{opt}`" for opt in all_opts]),
|
|
224
|
+
"{{< /multiline >}}",
|
|
225
|
+
]
|
|
226
|
+
)
|
|
227
|
+
default_value = ""
|
|
228
|
+
if param.default is not None:
|
|
229
|
+
default_value = f"`{param.default}`"
|
|
230
|
+
default_value = default_value.replace(f"{getcwd()}/", "")
|
|
231
|
+
help_text = dedent(param.help) if param.help else ""
|
|
232
|
+
table_data.append([opts, f"`{param.type.name}`", default_value, help_text])
|
|
233
|
+
|
|
234
|
+
if not table_data:
|
|
235
|
+
continue
|
|
236
|
+
|
|
237
|
+
# Add table header with proper alignment
|
|
238
|
+
output.append("")
|
|
239
|
+
output.append("| Option | Type | Default | Description |")
|
|
240
|
+
output.append("|--------|------|---------|-------------|")
|
|
241
|
+
|
|
242
|
+
# Add table rows with proper alignment
|
|
243
|
+
for row in table_data:
|
|
244
|
+
output.append(f"| {row[0]} | {row[1]} | {row[2]} | {row[3]} |")
|
|
245
|
+
|
|
246
|
+
# Generate verb index table
|
|
247
|
+
output_verb_index = []
|
|
248
|
+
has_plugin_verbs = False
|
|
249
|
+
|
|
250
|
+
if len(output_verb_groups) > 0:
|
|
251
|
+
output_verb_index.append("| Action | On |")
|
|
252
|
+
output_verb_index.append("| ------ | -- |")
|
|
253
|
+
for verb, nouns in output_verb_groups.items():
|
|
254
|
+
verb_is_plugin, _ = verb_metadata.get(verb, (False, None))
|
|
255
|
+
verb_display = verb
|
|
256
|
+
if verb_is_plugin:
|
|
257
|
+
verb_display = f"{verb}⁺"
|
|
258
|
+
has_plugin_verbs = True
|
|
259
|
+
|
|
260
|
+
if len(nouns) == 0:
|
|
261
|
+
verb_link = f"[`{verb_display}`](#flyte-{verb})"
|
|
262
|
+
output_verb_index.append(f"| {verb_link} | - |")
|
|
263
|
+
else:
|
|
264
|
+
# Create links for nouns
|
|
265
|
+
noun_links = []
|
|
266
|
+
for noun, noun_is_plugin, _ in nouns:
|
|
267
|
+
noun_display = noun
|
|
268
|
+
if noun_is_plugin:
|
|
269
|
+
noun_display = f"{noun}⁺"
|
|
270
|
+
has_plugin_verbs = True
|
|
271
|
+
noun_links.append(f"[`{noun_display}`](#flyte-{verb}-{noun})")
|
|
272
|
+
output_verb_index.append(f"| `{verb_display}` | {', '.join(noun_links)} |")
|
|
273
|
+
|
|
274
|
+
if has_plugin_verbs:
|
|
275
|
+
output_verb_index.append("")
|
|
276
|
+
output_verb_index.append("**⁺** Plugin command - see command documentation for installation instructions")
|
|
277
|
+
|
|
278
|
+
# Generate noun index table
|
|
279
|
+
output_noun_index = []
|
|
280
|
+
has_plugin_nouns = False
|
|
281
|
+
|
|
282
|
+
if len(output_noun_groups) > 0:
|
|
283
|
+
output_noun_index.append("| Object | Action |")
|
|
284
|
+
output_noun_index.append("| ------ | -- |")
|
|
285
|
+
for obj, actions in output_noun_groups.items():
|
|
286
|
+
action_links = []
|
|
287
|
+
for action, action_is_plugin, _ in actions:
|
|
288
|
+
action_display = action
|
|
289
|
+
if action_is_plugin:
|
|
290
|
+
action_display = f"{action}⁺"
|
|
291
|
+
has_plugin_nouns = True
|
|
292
|
+
action_links.append(f"[`{action_display}`](#flyte-{action}-{obj})")
|
|
293
|
+
output_noun_index.append(f"| `{obj}` | {', '.join(action_links)} |")
|
|
294
|
+
|
|
295
|
+
if has_plugin_nouns:
|
|
296
|
+
output_noun_index.append("")
|
|
297
|
+
output_noun_index.append("**⁺** Plugin command - see command documentation for installation instructions")
|
|
298
|
+
|
|
299
|
+
print()
|
|
300
|
+
print("{{< grid >}}")
|
|
301
|
+
print("{{< markdown >}}")
|
|
302
|
+
print("\n".join(output_noun_index))
|
|
303
|
+
print("{{< /markdown >}}")
|
|
304
|
+
print("{{< markdown >}}")
|
|
305
|
+
print("\n".join(output_verb_index))
|
|
306
|
+
print("{{< /markdown >}}")
|
|
307
|
+
print("{{< /grid >}}")
|
|
308
|
+
print()
|
|
309
|
+
print("\n".join(output))
|
|
310
|
+
|
|
311
|
+
|
|
312
|
+
def dedent(text: str) -> str:
|
|
313
|
+
"""
|
|
314
|
+
Remove leading whitespace from a string.
|
|
315
|
+
"""
|
|
316
|
+
return textwrap.dedent(text).strip("\n")
|