延伸点击¶
除了库本身中实现的常见功能外,还有无数模式可以通过扩展Click来实现。 本页应该深入了解可以实现的目标。
自定义组¶
您可以通过子类化自定义群组的行为,超出群组接受的参数 click.Group
.
最常见的覆盖方法是 get_command()
和 list_commands()
.
下面的示例实现了一个基本的插件系统,该系统从文件夹中的Python文件加载命令。该命令是懒惰加载的,以避免启动缓慢。
import importlib.util
import os
import click
class PluginGroup(click.Group):
def __init__(self, name=None, plugin_folder="commands", **kwargs):
super().__init__(name=name, **kwargs)
self.plugin_folder = plugin_folder
def list_commands(self, ctx):
rv = []
for filename in os.listdir(self.plugin_folder):
if filename.endswith(".py"):
rv.append(filename[:-3])
rv.sort()
return rv
def get_command(self, ctx, name):
path = os.path.join(self.plugin_folder, f"{name}.py")
spec = importlib.util.spec_from_file_location(name, path)
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
return module.cli
cli = PluginGroup(
plugin_folder=os.path.join(os.path.dirname(__file__), "commands")
)
if __name__ == "__main__":
cli()
自定义类也可以与装饰器一起使用:
@click.group(
cls=PluginGroup,
plugin_folder=os.path.join(os.path.dirname(__file__), "commands")
)
def cli():
pass
命令别名¶
许多工具支持命令别名。例如,您可以配置 git
接受 git ci
作为别名 git commit
.其他工具还支持通过自动缩短别名来自动发现别名。
可以定制 Group
以提供此功能。解释 自定义组 ,一群提供了两种方法: list_commands()
和 get_command()
.在这种特殊情况下,您只需要重写后者,因为您通常不想在帮助页面上列举别名以避免混淆。
下面的示例实现的一个子集 Group
它接受命令的前置。如果有一个命令被称为 push
,它会接受 pus
作为别名(只要它是唯一的):
class AliasedGroup(click.Group):
def get_command(self, ctx, cmd_name):
rv = super().get_command(ctx, cmd_name)
if rv is not None:
return rv
matches = [
x for x in self.list_commands(ctx)
if x.startswith(cmd_name)
]
if not matches:
return None
if len(matches) == 1:
return click.Group.get_command(self, ctx, matches[0])
ctx.fail(f"Too many matches: {', '.join(sorted(matches))}")
def resolve_command(self, ctx, args):
# always return the full command name
_, cmd, args = super().resolve_command(ctx, args)
return cmd.name, cmd, args
它可以这样使用:
@click.group(cls=AliasedGroup)
def cli():
pass
@cli.command
def push():
pass
@cli.command
def pop():
pass
看到 alias example 另一个例子是Click的存储库中。