Package: clickutil
clickutil - making click even better====================================Python's `click` package is an awesome tool for building command-lineinterfaces. But sometimes to use `click` the way I want to I need alot of boilerplate code, so I wrote `clickutil` to make my commandline packages more concise and less buggy.Keep access to your python functions by using `clickutil.call`--------------------------------------------------------------A normal click decorator looks something like this::@click.command('do-something')@click.option('--an-option', required=True, help='a click option')def do_something(an_option):click.echo(an_option)This can be frustrating if you want to expose a public api that is accessiblefrom both python and the command line, because the original `do_someting`function which took an argument is replaced by a function that takes noarguments and reads `sys.argv` for inputs.The `clickutil.call` decorator lets you instead decorate a placeholder functionas calling some function you want as part of your public api, so that theoriginal function may still be accessed from python::def do_something(an_option):click.echo(an_option)@click.command('do-something')@click.option('--an-option', required=True, help='a click option')@clickutil.call(do_something)def _do_something(): passAdd debugging using clickutil.debug-----------------------------------A common workflow for python developers is to load code from `ipython` and runit from the shell. There are several benefits to doing this, one of which isthat you can use the `%debug` magic command if unhandled exceptions occur.The `clickutils.debug` decorator lets you get a similar benefit when runningclick commands, by dropping into a debugger on unhandled exceptions. By defaultit adds an option `--debug`. When that flag is used, on any exceptions the clickendpoint will enter a debugger after delaying a few seconds (which gives theuser a chance to keyboard escape if they don't need to debug). The delay, andalso whether to debug by default, can both be configured.By default, `clickutil` will first try `pudb` and then `pdb` for debugging, butthis is configurable via an argument.For example, here we debug using `ipdb` after 10 seconds of waiting in theevent that `do_something` raises an exception. We do so by default, so toturn off this behavior you would need to use the `--no-debug` flag::import ipdb@click.command('do-something')@clickutil.debug(default=False, delay=10, use_debugger=ipdb)@clickutil.call(do_something)def _do_something(): passMore concise options and flags------------------------------The `click.option` function takes a lot of arguments to control differentkinds of behaviors, and conflates a lot of different kinds of options(for example, boolean flags like `--debug/--no-debug` get grouped togetherwith options that take arguments). Partly because the behavior of a clickoption depends on many different arguments, some of the default behaviors -- suchas not showing the default value of an option that has a default in the`--help` output -- don't make sense.To make working with options easier, `clickutil` provides three more specificfunctions: `clickutil.boolean_flag` for setting flags such as `--debug`,`clickutil.required_option` for options that take an argument and must beprovided, and `clickutil.default_option` for options that take an argumentand need not be provided. It also provides three special option types,`clickutil.EXISTING_FILE`, `clickutil.EXISTING_DIR`, and`clickutil.NEW_FILE_OR_DIR`, to handle the most common `click.Path` inputtypes.Detecting default values from function signatures-------------------------------------------------Because clickutil tries to keep the original python function availablefor calling from python using `clickutil.call`, it becomes irritating tohave to set default values for `default_option`s and `boolean_flag`s twice,both in the function and in the click decorators. In addition, the fact thatthese two can differ becomes a potential source of bugs.By inspecing the arguments of functions, `clickutil` is able to set defaultsbased on the argument list in the definition of a function.The `clickutil.boolean` decorator is similar to `clickutil.boolean_flag`,except it picks up its default value from the function signature. Similarly,`clickutil.option` is like `clickutil.required_option` or`clickutil.default_option`, depending on whether there's a default value in thefunction signature.