单击包含子模块

菲索林:

我正在尝试在我的第一个Click CLI应用程序上进行某种递归调用。重点是要有与第一个命令相关的子命令,因此,我试图将其全部分离到不同的文件/模块中,以提高其可维护性。

我有当前directory

root
|-commands
|-project
|---__init__
|---command1
|---command2
|-database
|---__init__
|---command1
|---command2

这是我的主文件:

import click
from commands.project import project
from commands.database import database


@click.group(help="Main command")
def main():
    pass


main.add_command(project)
main.add_command(database)

我的项目__init__文件:

from commands.project.command1 import *
from commands.project.command2 import *
import click


@click.group(help="Projects")
def project():
    pass


project.add_command(command1)
project.add_command(command2)

我的commands.project.command1档案:

import click


@click.command()
def command1():
    """
    Execute all the steps required to update the project.
    """
    pass

这里的要点是,每次我想添加一个新的子命令时,我都需要:

  1. .py包含所有代码的文件添加到命令中相应的subcommand / submodule文件夹中(显然!)。

  2. import__init__文件添加语句

  3. 将此新命令与其父级(在这种情况下为项目/数据库)相关联

有什么方法可以进行圆形/动态载荷以避免步骤2和3?


编辑

在尝试了Stephen Rauch的方法之后,它成功地包含了所有提供的文件,但是没有一个命令-仅适用于函数名(例如: -> )。 update-project update_project

root
|-commands
|-project
|---update
|---install_project
|-database
|---command_one
|---command_two

main.py

# main command ----------------------------------------------------------- ###
@click.group(help="CLI tool!", context_settings=dict(max_content_width=120))
def main():
    pass


# PROJECT command group -------------------------------------------------------- ###
@main.group(cls=group_from_folder("commands/project"),
            short_help="Project installation and upgrade utils.",
            help="Project installation and upgrade.")
def project():
    pass

命令/项目/ install_project.py

import click    

@click.command(name="install-project",
               help="This options allows you to easily install project",
               short_help="Install a brand new project")
@click.pass_context
def install_project(ctx):

CLI结果main project --help (注意install_project相反的install-projectsub命令)

Usage: main project [OPTIONS] COMMAND [ARGS]...

  Project installation and upgrade.

Options:
  --help  Show this message and exit.

Commands:
  install_project                     Install a brand new project one
Oleksandr Yarushevskyi:

我建议您只从特定的Python包中读取命令,然后将其添加到您的输入组中。

假设我们有这样的结构:

|--app
   |--commands
      |--__init__.py
      |--group1
         |--__init__.py
         |--command1.py
      |--group2
         |--__init__.py
         |--command2.py
|--__init__.py
|--cli.py

然后您的命令文件需要包含一键单击。具有指定名称的命令和具有名称``命令''的函数:

import click

@click.command(name="your-first-command")
def command():
    pass

每个组中的初始化文件都需要包含doc字符串,以使click.Group具有正确的“帮助”值。

最有趣的cli.py:

import click
import importlib
import pkgutil
import os.path


def get_commands_from_pkg(pkg) -> dict:
    pkg_obj = importlib.import_module(pkg)

    pkg_path = os.path.dirname(pkg_obj.__file__)

    commands = {}
    for module in pkgutil.iter_modules([pkg_path]):
        module_obj = importlib.import_module(f"{pkg}.{module.name}")
        if not module.ispkg:
            commands[module_obj.command.name] = module_obj.command

        else:
            commands[module.name.replace('_', '-')] = click.Group(
                context_settings={'help_option_names': ['-h', '--help']},
                help=module_obj.__doc__,
                commands=get_commands_from_pkg(f"{pkg}.{module.name}")
            )

    return commands


@click.group(context_settings={'help_option_names': ['-h', '--help']}, help="Your CLI",
             commands=get_commands_from_pkg('app.commands'))
def cli():
    pass

如您所见,我们以递归方式创建点击组并将点击命令添加到特定的组。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章