ShiErFeng/shierfeng-fastapi-backend/cli/completion/providers.py
2026-07-24 09:43:10 +08:00

1023 lines
35 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import asyncio
import os
from dataclasses import dataclass, field
from importlib import import_module
from pathlib import Path
from typing import Any
import click
from cli.metadata import (
COMPLETION_SHELL_SPEC_REGISTRY,
ENVIRONMENT_OPTION_SERVICE,
CompletionShellSpecRegistry,
EnvironmentOptionService,
)
DEFAULT_ALEMBIC_REVISION_CHOICES = ('head', 'base', 'current', '-1')
DYNAMIC_COMPLETION_TIMEOUT_SECONDS = 0.8
@dataclass(frozen=True)
class CompletionContextResolver:
"""
shell completion 上下文解析器。
该对象负责解析当前补全场景下的环境、缓存名称和项目目录,
将原本散落的参数与环境变量解析逻辑收口到单一职责对象中。
"""
def resolve_completion_env(self, ctx: click.Context | None) -> str:
"""
解析当前 completion 场景使用的环境名称。
:param ctx: Click 上下文
:return: 环境名称,默认返回 `dev`
"""
if ctx is not None:
env_value = getattr(ctx, 'params', {}).get('env')
if isinstance(env_value, str) and env_value.strip():
return env_value.strip()
comp_words = os.environ.get('COMP_WORDS', '').strip()
if comp_words:
tokens = comp_words.split()
for index, token in enumerate(tokens):
if token.startswith('--env='):
env_value = token.split('=', 1)[1].strip()
if env_value:
return env_value
if token == '--env' and index + 1 < len(tokens):
env_value = tokens[index + 1].strip()
if env_value:
return env_value
return 'dev'
def resolve_cache_name_for_completion(self, ctx: click.Context | None) -> str:
"""
解析当前 cache key 补全场景使用的缓存名称。
:param ctx: Click 上下文
:return: 缓存名称,缺失时返回空字符串
"""
if ctx is not None:
cache_name = getattr(ctx, 'params', {}).get('cache_name')
if isinstance(cache_name, str) and cache_name.strip():
return cache_name.strip()
comp_words = os.environ.get('COMP_WORDS', '').strip()
if not comp_words:
return ''
tokens = comp_words.split()
try:
cache_index = tokens.index('cache')
except ValueError:
return ''
if cache_index + 2 >= len(tokens):
return ''
subcommand = tokens[cache_index + 1]
if subcommand not in {'get', 'ttl'}:
return ''
cache_name = tokens[cache_index + 2].strip()
if cache_name.startswith('-'):
return ''
return cache_name
@staticmethod
def resolve_project_dir() -> Path:
"""
获取当前 CLI 工作目录对应的项目根目录。
:return: 当前项目根目录
"""
return Path.cwd().resolve()
@staticmethod
def normalize_completion_prefix(incomplete: str) -> str:
"""
规范化补全输入前缀。
:param incomplete: 原始未完成输入
:return: 规范化后的前缀文本
"""
return incomplete.strip()
@staticmethod
def to_display_path(path: Path, *, project_dir: Path) -> str:
"""
将绝对路径转换为适合补全显示的路径文本。
:param path: 原始路径
:param project_dir: 项目根目录
:return: 用于 shell completion 的显示路径
"""
try:
relative_path = path.relative_to(project_dir)
return str(relative_path) or '.'
except ValueError:
return str(path)
@dataclass
class DynamicCompletionService:
"""
动态补全执行服务。
该服务负责 runtime 模块导入、只读协程执行、标准 payload 提取与
候选过滤,从而避免各补全函数继续复制相同的模板。
:param context_resolver: completion 上下文解析器
:param timeout_seconds: 动态补全超时时间
"""
context_resolver: CompletionContextResolver = field(default_factory=CompletionContextResolver)
timeout_seconds: float = DYNAMIC_COMPLETION_TIMEOUT_SECONDS
@staticmethod
def _scoped_app_env(env: str) -> Any:
"""
为动态补全临时注入 `APP_ENV` 环境变量。
`config.env` 在导入阶段会优先读取 `APP_ENV`,因此补全场景下
直接切换进程环境变量比改写 `sys.argv` 更稳定,也更符合当前
后端配置模块的解析约束。
:param env: 当前补全环境名称
:return: 环境变量恢复上下文
"""
class _CompletionEnvScope:
def __enter__(self) -> None:
self._original_app_env = os.environ.get('APP_ENV')
os.environ['APP_ENV'] = env
def __exit__(self, exc_type: object, exc: object, traceback: object) -> None:
if self._original_app_env is None:
os.environ.pop('APP_ENV', None)
else:
os.environ['APP_ENV'] = self._original_app_env
return _CompletionEnvScope()
def load_runtime_module(self, module_name: str) -> Any:
"""
加载动态补全依赖的 runtime 模块。
:param module_name: runtime 模块名
:return: 已导入模块
"""
return import_module(module_name)
def run_completion_coroutine(self, coroutine: Any, *, env: str) -> Any:
"""
在补全场景下执行异步只读查询,并临时注入 `APP_ENV`。
:param coroutine: 待执行协程
:param env: 当前补全环境名称
:return: 协程执行结果
"""
try:
with self._scoped_app_env(env):
return asyncio.run(asyncio.wait_for(coroutine, timeout=self.timeout_seconds))
finally:
if asyncio.iscoroutine(coroutine):
coroutine.close()
@staticmethod
def extract_completion_items(payload: dict[str, Any], field_name: str) -> list[str]:
"""
从 CLI 标准结果中提取补全候选字段列表。
:param payload: CLI 标准结果字典
:param field_name: 需要提取的字段名
:return: 去重后的字符串列表
"""
if not isinstance(payload, dict) or not payload.get('ok', False):
return []
items = payload.get('items')
if not isinstance(items, list):
page_payload = payload.get('page')
if isinstance(page_payload, dict):
items = page_payload.get('rows')
if not isinstance(items, list):
return []
candidates = []
for item in items:
if not isinstance(item, dict):
continue
value = item.get(field_name)
if isinstance(value, str) and value.strip():
candidates.append(value.strip())
return sorted(set(candidates))
@staticmethod
def extract_completion_values(payload: dict[str, Any], field_name: str) -> list[str]:
"""
从 CLI 标准结果中提取字符串或整数类型的补全候选值。
:param payload: CLI 标准结果字典
:param field_name: 需要提取的字段名
:return: 去重后的字符串列表
"""
if not isinstance(payload, dict) or not payload.get('ok', False):
return []
items = payload.get('items')
if not isinstance(items, list):
page_payload = payload.get('page')
if isinstance(page_payload, dict):
items = page_payload.get('rows')
if not isinstance(items, list):
return []
candidates = []
for item in items:
if not isinstance(item, dict):
continue
value = item.get(field_name)
if isinstance(value, str) and value.strip():
candidates.append(value.strip())
elif isinstance(value, int):
candidates.append(str(value))
return sorted(set(candidates))
@staticmethod
def extract_completion_list(payload: dict[str, Any], field_name: str) -> list[str]:
"""
从 CLI 标准结果中提取直接位于顶层字段的字符串列表。
该方法用于缓存键名等不走 `items/page.rows` 结构的场景,
使这类动态补全也能统一复用 runtime 对象加载与协程执行逻辑。
:param payload: CLI 标准结果字典
:param field_name: 需要提取的顶层字段名
:return: 去重后的字符串列表
"""
if not isinstance(payload, dict) or not payload.get('ok', False):
return []
items = payload.get(field_name)
if not isinstance(items, list):
return []
candidates = [item.strip() for item in items if isinstance(item, str) and item.strip()]
return sorted(set(candidates))
@staticmethod
def filter_candidates(candidates: list[str], incomplete: str) -> list[str]:
"""
按未完成输入前缀过滤候选值。
:param candidates: 原始候选列表
:param incomplete: 当前未完成输入
:return: 过滤后的候选列表
"""
normalized_incomplete = incomplete.strip().lower()
return [candidate for candidate in candidates if candidate.lower().startswith(normalized_incomplete)]
def complete_dynamic_items(
self,
ctx: click.Context | None,
incomplete: str,
*,
runtime_module_name: str,
runtime_object_name: str | None = None,
runtime_method_name: str,
runtime_kwargs: dict[str, Any],
field_name: str,
allow_int_values: bool = False,
) -> list[str]:
"""
执行通用的动态只读补全查询。
:param ctx: Click 上下文
:param incomplete: 当前未完成输入
:param runtime_module_name: runtime 模块名
:param runtime_object_name: runtime 对象名,为空时直接使用模块
:param runtime_method_name: runtime 方法名
:param runtime_kwargs: runtime 调用参数
:param field_name: 待提取字段名
:param allow_int_values: 是否允许整数候选
:return: 过滤后的候选列表
"""
env = self.context_resolver.resolve_completion_env(ctx)
try:
runtime_module = self.load_runtime_module(runtime_module_name)
runtime_target = getattr(runtime_module, runtime_object_name) if runtime_object_name else runtime_module
runtime_method = getattr(runtime_target, runtime_method_name)
payload = self.run_completion_coroutine(runtime_method(**runtime_kwargs), env=env)
except Exception:
return []
if allow_int_values:
candidates = self.extract_completion_values(payload, field_name)
else:
candidates = self.extract_completion_items(payload, field_name)
return self.filter_candidates(candidates, incomplete)
def complete_dynamic_list(
self,
ctx: click.Context | None,
incomplete: str,
*,
runtime_module_name: str,
runtime_object_name: str | None = None,
runtime_method_name: str,
runtime_args: tuple[Any, ...] = (),
runtime_kwargs: dict[str, Any] | None = None,
field_name: str,
) -> list[str]:
"""
执行返回顶层字符串列表字段的动态只读补全查询。
:param ctx: Click 上下文
:param incomplete: 当前未完成输入
:param runtime_module_name: runtime 模块名
:param runtime_object_name: runtime 对象名,为空时直接使用模块
:param runtime_method_name: runtime 方法名
:param runtime_args: runtime 位置参数
:param runtime_kwargs: runtime 关键字参数
:param field_name: 顶层列表字段名
:return: 过滤后的候选列表
"""
env = self.context_resolver.resolve_completion_env(ctx)
try:
runtime_module = self.load_runtime_module(runtime_module_name)
runtime_target = getattr(runtime_module, runtime_object_name) if runtime_object_name else runtime_module
runtime_method = getattr(runtime_target, runtime_method_name)
payload = self.run_completion_coroutine(
runtime_method(*runtime_args, **(runtime_kwargs or {})),
env=env,
)
except Exception:
return []
candidates = self.extract_completion_list(payload, field_name)
return self.filter_candidates(candidates, incomplete)
@dataclass
class StaticCompletionProvider:
"""
静态 completion 提供器。
该对象负责 shell、环境、缓存名称以及 Alembic revision 等静态或
本地推导型补全候选。
:param context_resolver: completion 上下文解析器
:param dynamic_service: 动态补全执行服务
:param shell_spec_registry: shell 元数据注册表
:param environment_option_service: 环境选项服务
"""
context_resolver: CompletionContextResolver = field(default_factory=CompletionContextResolver)
dynamic_service: DynamicCompletionService = field(
default_factory=lambda: DynamicCompletionService(context_resolver=CompletionContextResolver())
)
shell_spec_registry: CompletionShellSpecRegistry = field(default_factory=lambda: COMPLETION_SHELL_SPEC_REGISTRY)
environment_option_service: EnvironmentOptionService = field(default_factory=lambda: ENVIRONMENT_OPTION_SERVICE)
def list_completion_shells(self) -> list[str]:
"""
获取已声明的 completion shell 列表。
:return: shell 名称列表
"""
return self.shell_spec_registry.list_shell_names()
def list_static_cache_names(self) -> list[str]:
"""
读取系统内置缓存名称列表。
:return: 缓存名称列表
"""
try:
redis_init_key_config = self.dynamic_service.load_runtime_module('common.enums').RedisInitKeyConfig
except Exception:
return []
return [key_config.key for key_config in redis_init_key_config if getattr(key_config, 'key', '')]
def complete_env_values(
self,
ctx: click.Context | None,
args: list[str] | None,
incomplete: str,
) -> list[str]:
"""
为 `--env` 选项提供可补全的环境名称。
:param ctx: Click 上下文
:param args: 当前命令参数列表
:param incomplete: 当前未完成输入片段
:return: 匹配的环境名称列表
"""
del ctx, args
normalized_incomplete = incomplete.strip().lower()
return [
env_name
for env_name in self.environment_option_service.discover_env_names()
if env_name.lower().startswith(normalized_incomplete)
]
def complete_shell_names(
self,
ctx: click.Context | None,
args: list[str] | None,
incomplete: str,
) -> list[str]:
"""
为 shell 参数提供静态补全结果。
:param ctx: Click 上下文
:param args: 当前命令参数列表
:param incomplete: 当前未完成输入片段
:return: shell 名称列表
"""
del ctx, args
normalized_incomplete = incomplete.strip().lower()
return [
shell_name for shell_name in self.list_completion_shells() if shell_name.startswith(normalized_incomplete)
]
def complete_cache_names(
self,
ctx: click.Context | None,
args: list[str] | None,
incomplete: str,
) -> list[str]:
"""
为缓存名称参数提供静态补全结果。
:param ctx: Click 上下文
:param args: 当前命令参数列表
:param incomplete: 当前未完成输入片段
:return: 缓存名称列表
"""
del ctx, args
normalized_incomplete = incomplete.strip().lower()
return [
cache_name
for cache_name in sorted(self.list_static_cache_names())
if cache_name.lower().startswith(normalized_incomplete)
]
def complete_alembic_revisions(
self,
ctx: click.Context | None,
args: list[str] | None,
incomplete: str,
) -> list[str]:
"""
为数据库迁移版本参数提供本地补全结果。
:param ctx: Click 上下文
:param args: 当前命令参数列表
:param incomplete: 当前未完成输入片段
:return: 迁移版本候选列表
"""
del ctx, args
normalized_incomplete = self.context_resolver.normalize_completion_prefix(incomplete).lower()
revision_choices = set(DEFAULT_ALEMBIC_REVISION_CHOICES)
versions_dir = self.context_resolver.resolve_project_dir() / 'alembic' / 'versions'
if versions_dir.is_dir():
for revision_file in versions_dir.glob('*.py'):
revision_stem = revision_file.stem
revision_id = revision_stem.split('-', 1)[-1].split('_', 1)[0].strip()
if revision_id:
revision_choices.add(revision_id)
return sorted(choice for choice in revision_choices if choice.lower().startswith(normalized_incomplete))
@dataclass
class PathCompletionProvider:
"""
路径 completion 提供器。
该对象负责项目相对 SQL 文件路径和输出路径补全。
:param context_resolver: completion 上下文解析器
"""
context_resolver: CompletionContextResolver = field(default_factory=CompletionContextResolver)
def complete_sql_files(
self,
ctx: click.Context | None,
args: list[str] | None,
incomplete: str,
) -> list[str]:
"""
为 SQL 文件参数提供项目内 `.sql` 文件补全结果。
:param ctx: Click 上下文
:param args: 当前命令参数列表
:param incomplete: 当前未完成输入片段
:return: SQL 文件路径列表
"""
del ctx, args
normalized_incomplete = self.context_resolver.normalize_completion_prefix(incomplete).lower()
project_dir = self.context_resolver.resolve_project_dir()
candidates = []
for sql_file in project_dir.rglob('*.sql'):
if '.git' in sql_file.parts or '__pycache__' in sql_file.parts:
continue
display_path = self.context_resolver.to_display_path(sql_file, project_dir=project_dir)
if display_path.lower().startswith(normalized_incomplete):
candidates.append(display_path)
return sorted(candidates)
def complete_output_paths(
self,
ctx: click.Context | None,
args: list[str] | None,
incomplete: str,
) -> list[str]:
"""
为导出文件参数提供目录和 `.zip` 文件补全结果。
:param ctx: Click 上下文
:param args: 当前命令参数列表
:param incomplete: 当前未完成输入片段
:return: 目录或 zip 文件路径列表
"""
del ctx, args
raw_incomplete = self.context_resolver.normalize_completion_prefix(incomplete)
project_dir = self.context_resolver.resolve_project_dir()
expanded_input = Path(raw_incomplete).expanduser()
input_is_absolute = expanded_input.is_absolute()
if raw_incomplete.endswith(('/', os.sep)):
search_dir = expanded_input if input_is_absolute else (project_dir / expanded_input).resolve()
partial_name = ''
else:
search_dir = (
expanded_input.parent
if input_is_absolute
else (
project_dir / expanded_input.parent if str(expanded_input.parent) != '.' else project_dir
).resolve()
)
partial_name = expanded_input.name
if not search_dir.exists() or not search_dir.is_dir():
return []
candidates = []
for child_path in sorted(search_dir.iterdir()):
if not child_path.name.startswith(partial_name):
continue
if child_path.is_dir():
display_path = self.context_resolver.to_display_path(child_path, project_dir=project_dir)
candidates.append(f'{display_path}/')
continue
if child_path.suffix.lower() == '.zip':
candidates.append(self.context_resolver.to_display_path(child_path, project_dir=project_dir))
return candidates
@dataclass
class DomainDynamicCompletionProvider:
"""
业务域动态 completion 提供器。
该对象负责配置、代码生成、缓存、任务等运行时驱动的只读补全。
:param context_resolver: completion 上下文解析器
:param dynamic_service: 动态补全执行服务
"""
context_resolver: CompletionContextResolver = field(default_factory=CompletionContextResolver)
dynamic_service: DynamicCompletionService = field(init=False)
def __post_init__(self) -> None:
"""
初始化动态补全执行服务。
:return: None
"""
self.dynamic_service = DynamicCompletionService(context_resolver=self.context_resolver)
def complete_config_keys(
self,
ctx: click.Context | None,
args: list[str] | None,
incomplete: str,
) -> list[str]:
"""
为参数键名提供动态只读补全结果。
:param ctx: Click 上下文
:param args: 当前命令参数列表
:param incomplete: 当前未完成输入片段
:return: 参数键名列表
"""
del args
return self.dynamic_service.complete_dynamic_items(
ctx,
incomplete,
runtime_module_name='cli.runtime.config',
runtime_object_name='CONFIG_RUNTIME',
runtime_method_name='list_configs',
runtime_kwargs={'config_key': incomplete, 'paged': True, 'page_num': 1, 'page_size': 20},
field_name='configKey',
)
def complete_gen_table_names(
self,
ctx: click.Context | None,
args: list[str] | None,
incomplete: str,
) -> list[str]:
"""
为代码生成业务表名称提供动态只读补全结果。
:param ctx: Click 上下文
:param args: 当前命令参数列表
:param incomplete: 当前未完成输入片段
:return: 业务表名称列表
"""
del args
return self.dynamic_service.complete_dynamic_items(
ctx,
incomplete,
runtime_module_name='cli.runtime.gen',
runtime_object_name='GEN_RUNTIME',
runtime_method_name='list_gen_tables',
runtime_kwargs={'table_name': incomplete, 'paged': True, 'page_num': 1, 'page_size': 20},
field_name='tableName',
)
def complete_gen_db_table_names(
self,
ctx: click.Context | None,
args: list[str] | None,
incomplete: str,
) -> list[str]:
"""
为数据库物理表名称提供动态只读补全结果。
:param ctx: Click 上下文
:param args: 当前命令参数列表
:param incomplete: 当前未完成输入片段
:return: 数据库物理表名称列表
"""
del args
return self.dynamic_service.complete_dynamic_items(
ctx,
incomplete,
runtime_module_name='cli.runtime.gen',
runtime_object_name='GEN_RUNTIME',
runtime_method_name='list_gen_db_tables',
runtime_kwargs={'table_name': incomplete, 'paged': True, 'page_num': 1, 'page_size': 20},
field_name='tableName',
)
def complete_cache_keys(
self,
ctx: click.Context | None,
args: list[str] | None,
incomplete: str,
) -> list[str]:
"""
为缓存键名提供动态只读补全结果。
:param ctx: Click 上下文
:param args: 当前命令参数列表
:param incomplete: 当前未完成输入片段
:return: 缓存键名列表
"""
del args
cache_name = self.context_resolver.resolve_cache_name_for_completion(ctx)
if not cache_name:
return []
return self.dynamic_service.complete_dynamic_list(
ctx,
incomplete,
runtime_module_name='cli.runtime.cache',
runtime_object_name='CACHE_RUNTIME',
runtime_method_name='list_cache_keys',
runtime_args=(cache_name,),
field_name='keys',
)
def complete_job_names(
self,
ctx: click.Context | None,
args: list[str] | None,
incomplete: str,
) -> list[str]:
"""
为任务名称提供动态只读补全结果。
:param ctx: Click 上下文
:param args: 当前命令参数列表
:param incomplete: 当前未完成输入片段
:return: 任务名称列表
"""
del args
return self.dynamic_service.complete_dynamic_items(
ctx,
incomplete,
runtime_module_name='cli.runtime.job',
runtime_object_name='JOB_RUNTIME',
runtime_method_name='list_jobs',
runtime_kwargs={'job_name': incomplete, 'paged': True, 'page_num': 1, 'page_size': 20},
field_name='jobName',
)
def complete_job_ids(
self,
ctx: click.Context | None,
args: list[str] | None,
incomplete: str,
) -> list[str]:
"""
为任务 ID 提供动态只读补全结果。
:param ctx: Click 上下文
:param args: 当前命令参数列表
:param incomplete: 当前未完成输入片段
:return: 任务 ID 列表
"""
del args
return self.dynamic_service.complete_dynamic_items(
ctx,
incomplete,
runtime_module_name='cli.runtime.job',
runtime_object_name='JOB_RUNTIME',
runtime_method_name='list_jobs',
runtime_kwargs={'paged': True, 'page_num': 1, 'page_size': 20},
field_name='jobId',
allow_int_values=True,
)
@dataclass
class CompletionProviderRegistry:
"""
completion 提供器注册表。
该注册表只负责持有静态补全、路径补全与动态只读补全 provider
供上层 gateway、安装器与其他协作者按职责选择使用。
:param context_resolver: completion 上下文解析器
:param dynamic_service: 动态补全执行服务
:param static_provider: 静态 completion 提供器
:param path_provider: 路径 completion 提供器
:param domain_provider: 业务域动态 completion 提供器
"""
context_resolver: CompletionContextResolver = field(default_factory=CompletionContextResolver)
dynamic_service: DynamicCompletionService = field(init=False)
static_provider: StaticCompletionProvider = field(init=False)
path_provider: PathCompletionProvider = field(init=False)
domain_provider: DomainDynamicCompletionProvider = field(init=False)
def __post_init__(self) -> None:
"""
初始化聚合 provider 依赖。
:return: None
"""
self.dynamic_service = DynamicCompletionService(context_resolver=self.context_resolver)
self.static_provider = StaticCompletionProvider(
context_resolver=self.context_resolver,
dynamic_service=self.dynamic_service,
)
self.path_provider = PathCompletionProvider(context_resolver=self.context_resolver)
self.domain_provider = DomainDynamicCompletionProvider(context_resolver=self.context_resolver)
self.domain_provider.dynamic_service = self.dynamic_service
@dataclass
class CompletionProviderGateway:
"""
completion 对外网关。
该对象负责对命令声明层、上下文层和 TUI 层暴露统一的 completion 入口,
避免 `CompletionProviderRegistry` 本体继续膨胀为大而全的委托门面。
:param provider_registry: completion provider 注册表
"""
provider_registry: CompletionProviderRegistry = field(default_factory=CompletionProviderRegistry)
def list_completion_shells(self) -> list[str]:
"""
获取已声明的 completion shell 列表。
:return: shell 名称列表
"""
return self.provider_registry.static_provider.list_completion_shells()
def list_static_cache_names(self) -> list[str]:
"""
读取系统内置缓存名称列表。
:return: 缓存名称列表
"""
return self.provider_registry.static_provider.list_static_cache_names()
def complete_env_values(
self,
ctx: click.Context | None,
args: list[str] | None,
incomplete: str,
) -> list[str]:
"""
为 `--env` 选项提供可补全的环境名称。
:param ctx: Click 上下文
:param args: 当前命令参数列表
:param incomplete: 当前未完成输入片段
:return: 匹配的环境名称列表
"""
return self.provider_registry.static_provider.complete_env_values(ctx, args, incomplete)
def complete_shell_names(
self,
ctx: click.Context | None,
args: list[str] | None,
incomplete: str,
) -> list[str]:
"""
为 shell 参数提供静态补全结果。
:param ctx: Click 上下文
:param args: 当前命令参数列表
:param incomplete: 当前未完成输入片段
:return: shell 名称列表
"""
return self.provider_registry.static_provider.complete_shell_names(ctx, args, incomplete)
def complete_cache_names(
self,
ctx: click.Context | None,
args: list[str] | None,
incomplete: str,
) -> list[str]:
"""
为缓存名称参数提供静态补全结果。
:param ctx: Click 上下文
:param args: 当前命令参数列表
:param incomplete: 当前未完成输入片段
:return: 缓存名称列表
"""
return self.provider_registry.static_provider.complete_cache_names(ctx, args, incomplete)
def complete_alembic_revisions(
self,
ctx: click.Context | None,
args: list[str] | None,
incomplete: str,
) -> list[str]:
"""
为数据库迁移版本参数提供本地补全结果。
:param ctx: Click 上下文
:param args: 当前命令参数列表
:param incomplete: 当前未完成输入片段
:return: 迁移版本候选列表
"""
return self.provider_registry.static_provider.complete_alembic_revisions(ctx, args, incomplete)
def complete_sql_files(
self,
ctx: click.Context | None,
args: list[str] | None,
incomplete: str,
) -> list[str]:
"""
为 SQL 文件参数提供项目内 `.sql` 文件补全结果。
:param ctx: Click 上下文
:param args: 当前命令参数列表
:param incomplete: 当前未完成输入片段
:return: SQL 文件路径列表
"""
return self.provider_registry.path_provider.complete_sql_files(ctx, args, incomplete)
def complete_output_paths(
self,
ctx: click.Context | None,
args: list[str] | None,
incomplete: str,
) -> list[str]:
"""
为导出文件参数提供目录和 `.zip` 文件补全结果。
:param ctx: Click 上下文
:param args: 当前命令参数列表
:param incomplete: 当前未完成输入片段
:return: 目录或 zip 文件路径列表
"""
return self.provider_registry.path_provider.complete_output_paths(ctx, args, incomplete)
def complete_config_keys(
self,
ctx: click.Context | None,
args: list[str] | None,
incomplete: str,
) -> list[str]:
"""
为参数键名提供动态只读补全结果。
:param ctx: Click 上下文
:param args: 当前命令参数列表
:param incomplete: 当前未完成输入片段
:return: 参数键名列表
"""
return self.provider_registry.domain_provider.complete_config_keys(ctx, args, incomplete)
def complete_gen_table_names(
self,
ctx: click.Context | None,
args: list[str] | None,
incomplete: str,
) -> list[str]:
"""
为代码生成业务表名称提供动态只读补全结果。
:param ctx: Click 上下文
:param args: 当前命令参数列表
:param incomplete: 当前未完成输入片段
:return: 业务表名称列表
"""
return self.provider_registry.domain_provider.complete_gen_table_names(ctx, args, incomplete)
def complete_gen_db_table_names(
self,
ctx: click.Context | None,
args: list[str] | None,
incomplete: str,
) -> list[str]:
"""
为数据库物理表名称提供动态只读补全结果。
:param ctx: Click 上下文
:param args: 当前命令参数列表
:param incomplete: 当前未完成输入片段
:return: 数据库物理表名称列表
"""
return self.provider_registry.domain_provider.complete_gen_db_table_names(ctx, args, incomplete)
def complete_cache_keys(
self,
ctx: click.Context | None,
args: list[str] | None,
incomplete: str,
) -> list[str]:
"""
为缓存键名提供动态只读补全结果。
:param ctx: Click 上下文
:param args: 当前命令参数列表
:param incomplete: 当前未完成输入片段
:return: 缓存键名列表
"""
return self.provider_registry.domain_provider.complete_cache_keys(ctx, args, incomplete)
def complete_job_names(
self,
ctx: click.Context | None,
args: list[str] | None,
incomplete: str,
) -> list[str]:
"""
为任务名称提供动态只读补全结果。
:param ctx: Click 上下文
:param args: 当前命令参数列表
:param incomplete: 当前未完成输入片段
:return: 任务名称列表
"""
return self.provider_registry.domain_provider.complete_job_names(ctx, args, incomplete)
def complete_job_ids(
self,
ctx: click.Context | None,
args: list[str] | None,
incomplete: str,
) -> list[str]:
"""
为任务 ID 提供动态只读补全结果。
:param ctx: Click 上下文
:param args: 当前命令参数列表
:param incomplete: 当前未完成输入片段
:return: 任务 ID 列表
"""
return self.provider_registry.domain_provider.complete_job_ids(ctx, args, incomplete)
COMPLETION_PROVIDER_REGISTRY = CompletionProviderRegistry()
COMPLETION_PROVIDER_GATEWAY = CompletionProviderGateway(provider_registry=COMPLETION_PROVIDER_REGISTRY)