Cleo 允许您创建美观且可测试的命令行界面。
项目描述
Cleo
创建美观且可测试的命令行界面。
资源
使用方法
要创建一个从命令行问候您的命令,创建 greet_command.py 并将以下内容添加到其中
from cleo.commands.command import Command
from cleo.helpers import argument, option
class GreetCommand(Command):
    name = "greet"
    description = "Greets someone"
    arguments = [
        argument(
            "name",
            description="Who do you want to greet?",
            optional=True
        )
    ]
    options = [
        option(
            "yell",
            "y",
            description="If set, the task will yell in uppercase letters",
            flag=True
        )
    ]
    def handle(self):
        name = self.argument("name")
        if name:
            text = f"Hello {name}"
        else:
            text = "Hello"
        if self.option("yell"):
            text = text.upper()
        self.line(text)
您还需要创建一个名为 application.py 的文件,以便在命令行中运行,它将创建一个 Application 并向其中添加命令
#!/usr/bin/env python
from greet_command import GreetCommand
from cleo.application import Application
application = Application()
application.add(GreetCommand())
if __name__ == "__main__":
    application.run()
通过运行以下命令来测试新命令
$ python application.py greet John
这将打印以下内容到命令行
Hello John
您还可以使用 --yell 选项将所有内容转换为大写
$ python application.py greet John --yell
这会打印
HELLO JOHN
输出着色
每次输出文本时,您都可以用标签将其包围以着色输出。例如
# blue text
self.line("<info>foo</info>")
# green text
self.line("<comment>foo</comment>")
# cyan text
self.line("<question>foo</question>")
# bold red text
self.line("<error>foo</error>")
关闭标签可以用 </> 替换,这将取消由最后一个打开的标签建立的任何格式化选项。
您可以使用 add_style() 方法定义自己的样式
self.add_style("fire", fg="red", bg="yellow", options=["bold", "blink"])
self.line("<fire>foo</fire>")
可用的前景色和背景色有:black(黑色)、red(红色)、green(绿色)、yellow(黄色)、blue(蓝色)、magenta(洋红色)、cyan(青色)和 white(白色)。
可用的选项有:bold(加粗)、underscore(下划线)、blink(闪烁)、reverse(反转)和 conceal(隐藏)。
您也可以在标签名称内设置这些颜色和选项
# green text
self.line("<fg=green>foo</>")
# black text on a cyan background
self.line("<fg=black;bg=cyan>foo</>")
# bold text on a yellow background
self.line("<bg=yellow;options=bold>foo</>")
详细程度级别
Cleo 有四个详细程度级别。这些在 Output 类中定义
| 模式 | 含义 | 控制台选项 | 
|---|---|---|
| Verbosity.QUIET | 不输出任何消息 | -q或--quiet | 
| Verbosity.NORMAL | 默认详细程度级别 | (无) | 
| Verbosity.VERBOSE | 消息的详细程度增加 | -v | 
| Verbosity.VERY_VERBOSE | 信息性非必要消息 | -vv | 
| Verbosity.DEBUG | 调试消息 | -vvv | 
您可以在命令中打印仅在特定详细程度级别上显示的消息。例如
if Verbosity.VERBOSE <= self.io.verbosity:
    self.line(...)
还有更多语义方法可以用来测试每个详细程度级别
if self.output.is_quiet():
    # ...
if self.output.is_verbose():
    # ...
您也可以直接将详细程度标志传递给 line()。
self.line("", verbosity=Verbosity.VERBOSE)
当使用安静级别时,所有输出都将被抑制。
使用参数
命令最有意思的部分是您可以提供的参数和选项。参数是命令名称之后由空格分隔的字符串。它们是有序的,可以是可选的或必需的。例如,向命令添加一个可选的 last_name 参数并使 name 参数成为必需的
class GreetCommand(Command):
    name = "greet"
    description = "Greets someone"
    arguments = [
        argument(
            "name",
            description="Who do you want to greet?",
        ),
        argument(
            "last_name",
            description="Your last name?",
            optional=True
        )
    ]
    options = [
        option(
            "yell",
            "y",
            description="If set, the task will yell in uppercase letters",
            flag=True
        )
    ]
现在您可以在您的命令中访问 last_name 参数
last_name = self.argument("last_name")
if last_name:
    text += f" {last_name}"
命令现在可以使用以下两种方式之一使用
$ python application.py greet John
$ python application.py greet John Doe
您还可以让一个参数接受一系列值(假设您想问候所有的朋友)。为此,必须在参数列表的末尾指定
class GreetCommand(Command):
    name = "greet"
    description = "Greets someone"
    arguments = [
        argument(
            "names",
            description="Who do you want to greet?",
            multiple=True
        )
    ]
    options = [
        option(
            "yell",
            "y",
            description="If set, the task will yell in uppercase letters",
            flag=True
        )
    ]
要使用此功能,只需指定您想要的名称数量即可
$ python application.py greet John Jane
您可以将 names 参数作为列表访问
names = self.argument("names")
if names:
    text = "Hello " + ", ".join(names)
使用选项
与参数不同,选项是无序的(这意味着您可以用任何顺序指定它们),并且用两个短横线指定(例如 --yell - 您也可以声明一个单字母快捷键,您可以用单个短横线调用它,如 -y)。选项总是可选的,并且可以设置为接受一个值(例如 --dir=src)或简单地作为一个没有值的布尔标志(例如 --yell)。
提示:您也可以使一个选项 可选地 接受一个值(这样
--yell或--yell=loud都可以工作)。选项也可以配置为接受值的列表。
例如,向命令添加一个新选项,用于指定消息应连续打印多少次
class GreetCommand(Command):
    name = "greet"
    description = "Greets someone"
    arguments = [
        argument(
            "name",
            description="Who do you want to greet?",
            optional=True
        )
    ]
    options = [
        option(
            "yell",
            "y",
            description="If set, the task will yell in uppercase letters",
            flag=True
        ),
        option(
            "iterations",
            description="How many times should the message be printed?",
            default=1
        )
    ]
接下来,在命令中使用此功能来多次打印消息
for _ in range(int(self.option("iterations"))):
    self.line(text)
现在,当您运行任务时,您可以可选地指定一个 --iterations 标志
$ python application.py greet John
$ python application.py greet John --iterations=5
第一个示例只会打印一次,因为iterations为空,默认为1。第二个示例将打印五次。
请记住,选项不关心它们的顺序。因此,以下两种方式都可以工作
$ python application.py greet John --iterations=5 --yell
$ python application.py greet John --yell --iterations=5
测试命令
Cleo提供了一些工具来帮助您测试命令。其中最有用的是CommandTester类。它使用特殊的IO类来简化测试,而无需真实的控制台
from greet_command import GreetCommand
from cleo.application import Application
from cleo.testers.command_tester import CommandTester
def test_execute():
    application = Application()
    application.add(GreetCommand())
    command = application.find("greet")
    command_tester = CommandTester(command)
    command_tester.execute()
    assert "..." == command_tester.io.fetch_output()
CommandTester.io.fetch_output()方法返回在正常控制台调用期间将被显示的内容。CommandTester.io.fetch_error()也可用,用于获取写入到stderr的内容。
您可以通过将参数和选项作为字符串传递给CommandTester.execute()方法来测试向命令发送参数和选项
from greet_command import GreetCommand
from cleo.application import Application
from cleo.testers.command_tester import CommandTester
def test_execute():
    application = Application()
    application.add(GreetCommand())
    command = application.find("greet")
    command_tester = CommandTester(command)
    command_tester.execute("John")
    assert "John" in command_tester.io.fetch_output()
您还可以使用ApplicationTester类来测试整个控制台应用程序。
调用现有命令
如果一个命令依赖于另一个命令先运行,而不是让用户记住执行顺序,您可以直接自己调用它。如果您想要创建一个仅运行其他命令的“元”命令,这也很有用。
从一个命令中调用另一个命令非常简单
def handle(self):
    return_code = self.call("greet", "John --yell")
    return return_code
如果您想抑制已执行命令的输出,可以使用call_silent()方法。
自动补全
Cleo支持在bash、zsh和fish中的自动(Tab)补全。
默认情况下,您的应用程序将有一个completions命令。要在终端中注册这些补全命令,请运行以下之一(将[program]替换为您运行应用程序的命令)
# Bash
[program] completions bash | sudo tee /etc/bash_completion.d/[program].bash-completion
# Bash - macOS/Homebrew (requires `brew install bash-completion`)
[program] completions bash > $(brew --prefix)/etc/bash_completion.d/[program].bash-completion
# Zsh
mkdir ~/.zfunc
echo "fpath+=~/.zfunc" >> ~/.zshrc
[program] completions zsh > ~/.zfunc/_[program]
# Zsh - macOS/Homebrew
[program] completions zsh > $(brew --prefix)/share/zsh/site-functions/_[program]
# Fish
[program] completions fish > ~/.config/fish/completions/[program].fish
          项目详情
下载文件
下载适用于您的平台的文件。如果您不确定选择哪个,请了解有关安装包的更多信息。