cli2 Python API Documentation

Command

class cli2.command.Command(target, *args, **kwargs)[source]

Represents a command bound to a target callable.

arg(name, *, kind: str = None, position: int = None, doc=None, color=None, default, annotation)[source]

Inject new Argument into this command.

The new argument will appear in documentation, but won’t be bound to the callable: it will only be avalaible in self.

For example, you are deleting an “http_client” argument in setargs() so that it doesn’t appear to the CLI user, to whom you want to expose a couple of arguments such as “base_url” and “ssl_verify” that you are adding programatically with this method, so that you can use self[‘base_url’].value and self[‘ssl_verify’].value in to generate a “http_client” argument in call().

The tutorial has a more comprehensive example in the “CLI only arguments” section.

Parameters:
  • name – Name of the argument to add

  • kind – Name of the inspect parameter kind

  • position – Position of the argument in the CLI

  • doc – Documentation for the argument

  • color – Color of the argument

  • default – Default value for the argument

  • annotation – Type of argument

async async_call(*argv)[source]

Call with async stuff in single event loop

async_function(function)[source]

Return True if function is async

async_mode()[source]

Return True if any callable we’ll deal with is async

call(*args, **kwargs)[source]

Execute command target with bound arguments.

help(error=None, short=False, missing=None)[source]

Show help for a command.

items(factories=False)[source]

Return ordered items.

Parameters:

factories – Show only arguments with factory.

keys(factories=False)[source]

Return ordered keys.

Parameters:

factories – Show only arguments with factory.

ordered(factories=False)[source]

Order the parameters by priority.

Parameters:

factories – Show only arguments with factory.

parse(*argv)[source]

Parse arguments into BoundArguments.

post_call()[source]

Implement your cleaner here

setargs()[source]

Reset arguments.

values(factories=False)[source]

Return ordered values.

Parameters:

factories – Show only arguments with factory.

Group

class cli2.group.Group(name=None, doc=None, color=None, posix=False, overrides=None, outfile=None, cmdclass=None, log=True)[source]

Represents a group of named commands.

add(target, *args, **kwargs)[source]

Add a new target as sub-command.

cmd(*args, **kwargs)[source]

Decorator to add a command with optionnal overrides.

group(name, **kwargs)[source]

Return a new sub-group.

help(*args, error=None, short=False)[source]

Get help for a command or group.

Parameters:
  • args – Command or sub-command chain to show help for.

  • error – Error message to print out.

  • short – Show short documentation.

load(obj, parent=None, public=True)[source]

Load a Python object callables into sub-commands.

load_cls(cls, exclude=None)[source]

Load all methods which have been decorated with @cmd

Argument

class cli2.argument.Argument(cmd, param, doc=None, color=None, factory=None, hide=False, **kwargs)[source]

Class representing a bound parameter and command line argument.

property accepts

Return True if this argument still accepts values to bind.

aliasmatch(arg)[source]

Return True if the CLI arg matches an alias of this argument.

cast(value)[source]

Cast a string argument from the CLI into a Python object.

factory_value()[source]

Run the factory function and return the value.

If the factory function takes a cmd argument, it will pass the command object.

If the factory function takes an arg argument, it will pass self.

help()[source]

Render help for this argument.

property iskw

Return True if this argument is not positional.

match(arg)[source]

Return the value extracted from a matching CLI argument.

take(arg)[source]

Return False if it doesn’t accept this arg, otherwise bind it.

property value

Return the value bound to this argument.

Decorators

cli2.decorators.arg(name, **kwargs)[source]

Set the overrides for an argument.

cli2.decorators.cmd(*args, **overrides)[source]

Set the overrides for a command.

Display

Generic pretty display utils.

This module defines a print function that’s supposed to be able to pretty-print anything, as well as a pretty diff printer.

cli2.display.diff(diff, **kwargs)[source]

Pretty-print a diff generated by Python’s standard difflib.unified_diff method.

# pretty print a diff
cli2.diff(difflib.unified_diff(old, new))
cli2.display.print(*args, **kwargs)[source]

Try to print the render()’ed args, pass the kwargs to actual print method.

# pretty print some_object
cli2.print(some_object)
cli2.display.render(arg)[source]

Try to render arg as yaml.

If the arg has a .json() method, it’ll be called. If it is parseable as JSON then it’l be parsed as such. Then, it’ll be dumped as colored YAML.

Set the env var FORCE_COLOR to anything to force into printing colors even if terminal is non-interactive (ie. gitlab-ci)

# pretty render some_object
print(cli2.render(some_object))

Colors

Define a bunch of arbitrary color ANSI color codes.

This module is available in the cli2.c namespace.

Example:

import cli2
print(f'{cli2.c.green2bold}OK{cli2.c.reset}')

See the following for details.

"""
Define a bunch of arbitrary color ANSI color codes.

This module is available in the `cli2.c` namespace.

Example:

.. code-block:: python

    import cli2
    print(f'{cli2.c.green2bold}OK{cli2.c.reset}')

See the following for details.
"""


colors = dict(
    cyan='\u001b[38;5;51m',
    cyan1='\u001b[38;5;87m',
    cyan2='\u001b[38;5;123m',
    cyan3='\u001b[38;5;159m',
    blue='\u001b[38;5;33m',
    blue1='\u001b[38;5;69m',
    blue2='\u001b[38;5;75m',
    blue3='\u001b[38;5;81m',
    blue4='\u001b[38;5;111m',
    blue5='\u001b[38;5;27m',
    green='\u001b[38;5;10m',
    green1='\u001b[38;5;2m',
    green2='\u001b[38;5;46m',
    green3='\u001b[38;5;47m',
    green4='\u001b[38;5;48m',
    green5='\u001b[38;5;118m',
    green6='\u001b[38;5;119m',
    green7='\u001b[38;5;120m',
    purple='\u001b[38;5;5m',
    purple1='\u001b[38;5;6m',
    purple2='\u001b[38;5;13m',
    purple3='\u001b[38;5;164m',
    purple4='\u001b[38;5;165m',
    purple5='\u001b[38;5;176m',
    purple6='\u001b[38;5;145m',
    purple7='\u001b[38;5;213m',
    purple8='\u001b[38;5;201m',
    red='\u001b[38;5;1m',
    red1='\u001b[38;5;9m',
    red2='\u001b[38;5;196m',
    red3='\u001b[38;5;160m',
    red4='\u001b[38;5;197m',
    red5='\u001b[38;5;198m',
    red6='\u001b[38;5;199m',
    yellow='\u001b[38;5;226m',
    yellow1='\u001b[38;5;227m',
    yellow2='\u001b[38;5;226m',
    yellow3='\u001b[38;5;229m',
    yellow4='\u001b[38;5;220m',
    yellow5='\u001b[38;5;230m',
    gray='\u001b[38;5;250m',
    gray1='\u001b[38;5;251m',
    gray2='\u001b[38;5;252m',
    gray3='\u001b[38;5;253m',
    gray4='\u001b[38;5;254m',
    gray5='\u001b[38;5;255m',
    gray6='\u001b[38;5;249m',
    pink='\u001b[38;5;199m',
    pink1='\u001b[38;5;198m',
    pink2='\u001b[38;5;197m',
    pink3='\u001b[38;5;200m',
    pink4='\u001b[38;5;201m',
    pink5='\u001b[38;5;207m',
    pink6='\u001b[38;5;213m',
    orange='\u001b[38;5;202m',
    orange1='\u001b[38;5;208m',
    orange2='\u001b[38;5;214m',
    orange3='\u001b[38;5;220m',
    orange4='\u001b[38;5;172m',
    orange5='\u001b[38;5;166m',
    bold='\033[1m',
    reset='\u001b[0m',
)

colors.update({
    k + 'bold': v.replace('[', '[1;')
    for k, v in colors.items()
})


class Colors:
    def __init__(self, colors):
        for name, value in colors.items():
            setattr(self, name, value)


colors = Colors(colors)

Configuration

12-factor interactive self-building lazy configuration.

The developer story we are after:

  • there’s nothing to do, just expect cli2.cfg['YOUR_ENV_VAR'] to work one way or another

  • when there’s a minute to be nice to the user, add some help that will be displayed to them: cli2.cfg.questions['YOUR_ENV_VAR'] = 'this is a help text that will be display to the user when we prompt them for YOUR_ENV_VAR'

This is the user story we are after:

  • user runs your cli2 command right after install without any configuration

  • the user is prompted for a variable

  • the variable is saved in their ~/.profile in a new export line

  • the user runs a command again in the same shell: we should find the variable in ~/.profile so he doesn’t have to start a new shell for his new configuration to work

Of course, if the environment variable is already present in the environment then this basically returns it from os.environ.

class cli2.configuration.Configuration(profile_path=None, **questions)[source]

Configuration object.

Wraps around environment variable and can question the user for missing variables and save them in his shell profile.

questions

A dict of ENV_VAR=question_string, if an env var is missing from configuration then question_string will be used as text to prompt the user.

profile_path

Path to the shell profile to save/read variables, defaults to ~/.profile which should work in many shells.

You can also just work with the module level (“singleton”) instance, have scripts like:

import cli2

cli = cli2.Group()

cli2.cfg['API_URL'] = 'What is your API URL?'

@cli.cmd
def foo():
    api_url = cli2.cfg['API_URL']

    # when there's no question, it'll use the var name as prompt
    api_url = cli2.cfg['USERNAME']
configure(key)[source]

Core logic to figure a variable.

  • if present in os.environ: return that

  • if parsed in profile_variables: return that

  • otherwise prompt it, with the question if any, then save it to profile_path

delete(key, reason=None)[source]

Delete a variable from everywhere, useful if an api key expired.

Parameters:
  • key – Env var name to delete

  • reason – Reason to print to the user

input(prompt)[source]

Wraps around Python’s input but adds confirmation.

Parameters:

prompt – Prompt text to display.

property profile_script

Cached profile_path reader.

property profile_variables

Cached environment variable parsing from profile_path.

Node

class cli2.node.Node(name, target, module=None)[source]

A Python node, used to browse python module programatically for callables.

property callables

Return the list of callables in this Node.

classmethod factory(name)[source]

Return a Node based on a string dotted python path.

Examples:

Node.factory('your.module')
Node.factory('your.module.your_object')
Node.factory('your.module.your_object.some_attribute')

Test

cli2.test.autotest(path, cmd, ignore=None, env=None)[source]

The autowriting test pattern, minimal for testing cli2 scripts.

Example:

from cli2.test import autotest
autotest(
    'tests/djcli_save_user.txt',
    'djcli save auth.User username="test"',
)