I am trying to create a command line application with hierarchical commands (my sub-commands will have sub-commands). However, when I attempt a very basic application, I get an AttributeError
.
I am able to replicate this with a simple example.
.
├── cli.py
└── commands
├── config_cmds.py
├── __init__.py
# -*- coding: utf-8 -*-
import sys
import click
from commands.config_cmds import configcmd
@click.group()
@click.version_option()
def cli(args=None):
"""A command line application"""
return 0
cli.add_command(configcmd)
if __name__ == "__main__":
sys.exit(cli()) # pragma: no cover
import click
@click.group
@click.version_option()
def configcmd():
"""Configuration management for this CLI"""
click.echo("In config")
If I run this application, I get the following error:
$ python cli.py
Traceback (most recent call last):
File "cli.py", line 15, in <module>
cli.add_command(configcmd)
File "/home/frank/.virtualenvs/clitest/lib/python3.6/site-packages/click/core.py", line 1221, in add_command
name = name or cmd.name
AttributeError: 'function' object has no attribute 'name'
My directory structure is set up based on this answer.
I am using python 3.6 and Click version 7.0.
How do I resolve this attribute error so that I can have a hierarchy of commands and keep the commands split into multiple files?
You need to call the click.group()
decorator like:
@click.group()
@click.version_option()
def configcmd():
"""Configuration management for this CLI"""
click.echo("In config")
import sys
import click
from commands.config_cmd import configcmd
@click.group()
@click.version_option()
def cli(args=None):
"""A command line application"""
return 0
cli.add_command(configcmd)
@configcmd.command()
def test_cmd():
click.echo('In test_cmd')
if __name__ == "__main__":
commands = (
'configcmd test_cmd',
'configcmd --help',
'--help',
'',
)
import sys, time
time.sleep(1)
print('Click Version: {}'.format(click.__version__))
print('Python Version: {}'.format(sys.version))
for cmd in commands:
try:
time.sleep(0.1)
print('-----------')
print('> ' + cmd)
time.sleep(0.1)
cli(cmd.split())
except BaseException as exc:
if str(exc) != '0' and \
not isinstance(exc, (click.ClickException, SystemExit)):
raise
Click Version: 6.7
Python Version: 3.6.3 (v3.6.3:2c5fed8, Oct 3 2017, 18:11:49) [MSC v.1900 64 bit (AMD64)]
-----------
> configcmd test_cmd
In config
In test_cmd
-----------
> configcmd --help
Usage: test.py configcmd [OPTIONS] COMMAND [ARGS]...
Configuration management for this CLI
Options:
--version Show the version and exit.
--help Show this message and exit.
Commands:
test_cmd
-----------
> --help
Usage: test.py [OPTIONS] COMMAND [ARGS]...
A command line application
Options:
--version Show the version and exit.
--help Show this message and exit.
Commands:
configcmd Configuration management for this CLI
-----------
>
Usage: test.py [OPTIONS] COMMAND [ARGS]...
A command line application
Options:
--version Show the version and exit.
--help Show this message and exit.
Commands:
configcmd Configuration management for this CLI