Why begins?

I write a lot of
small programs in Python.
These programs often
accept a small number of
simple command line arguments.
Having to write
command line parsing code
in each of these
small programs both
breaks my train of thought
and greatly increases the
volume of code I am writting.

Begins was implemented to
remove the boilerplate code
from these Python programs.
It’s not intended to replace
the rich command line processing
needed for larger applications.

Installation

Alternatively, the latest
development version can be
installed directly
from Github.

$ pip install git+https://github.com/aliles/begins.git

Please note that
begins is still in
an alpha state
and therefore
the API or behaviour
could change.

Setting a programs starting point

The begin.start() function can be
used as a function call
or a decorator.
If called as a function
it returns True when
called from the __main__ module.
To do this it inspects
the stack frame of the caller,
checking the __name__ global.

This allows the following Python pattern:

>>> if __name__ == '__main__':
... pass

To be replace with:

>>> import begin
>>> if begin.start():
... pass

If used as a decorator
to annotate a function
the function will be called
if defined in the __main__ module
as determined by inspecting
the current stack frame.
Any definitions that follow
the decorated function
wont be created until
after the function call
is complete.

Usage of begin.start() as
a decorator looks like:

>>> import begin
>>> @begin.start
... def run():
... pass

By deferring the execution
of the function until after
the remainder of the module has loaded
ensures the main function doesn’t fail
if depending on something
defined in later code.

Parsing command line options

If begin.start() decorates a
function accepts parameters
begin.start() will
process the command for
options to pass as
those parameters:

Command line parsing
does not support
variable length keyword arguments,
commonly written as
**kwargs.
If variable length keyword arguments
are used by
the decorated function
an exception
will be raised.

If a parameter
does not have a default,
failing to pass a value
on the command line
will cause running the program to
print an error and exit.

For programs that have
a large number of options
it may be preferable to
only use long options.
To suppress short options,
pass False as the
short_args keyword argument to
the begin.start decorator:

This program will list
the command line options as
alpha, beta, charlie
instead of the order
in which the function
accepts them.

Boolean options

If a command line option has
a default value that
is a bool object.
(True or False)
The command line option
will be flags
rather than an option
that accepts a value.
Two flags are generated,
one to set a True value and
one to set a False value.
The two commands will be of
the form --flag and --no-flag.
For example:

usage: subcommands.py [-h] {colour,name,quest} ...
optional arguments:
-h, --help show this help message and exit
Available subcommands:
{colour,name,quest}
colour What is your favourite colour?
name What is your name?
quest What is your quest?

The main function will
always be called with
the provided command line arguments.
If a sub-command was chosen
the associated function will
also be called.

It is possible to
create a sub-command with
a different name from
the decorated function’s name.
To do this pass the
desired sub-command name using
the name keyword argument:

Sub-commands can also be
registered with a
specific named group by
passing a group argument to
the begin.subcommand decorator.
The begin.start() decorator can
use sub-commands from
a named group by
passing it a sub_group argument.

Similarly, sub-commands can be
load from entry points by
passing the name
of the entry point
through the plugins argument
to the begin.start() decorator:

Any functions from
installed packages
that are registered with
the begins.plugin.demo entry point
will be loaded as sub-commands.

Multiple Sub-Commands

Some commands may benefit
from being able to be called with
multiple subcommands on
the command line.
The enable multiple sub-commands
a command separator value needs
to be passed to be
passed to begin.start()
as the cmd_delim parameter:

When this program is called
from the command line
multiple instances of the
sub-command may be called
if separated by the
command delimiter --.

Sub-Command Context

There are use cases where
it is desirable to pass
state from the main function to
a subsequent sub-command.
To support this Begins provides
the begin.context object.
This object will have the
following properties:

last_return, value returned by previous command function.

return_values, iterable of all return values from previous commands.

opts_previous, iterable of options object used by previous commands.

opts_current, options object for current command.

opts_next, iterable of options object for following commands.

(deprecated)return_value, replaced by last_return.

Any other properties set
on the begin.context object
will not be altered by begins.

The last_return property
and return_values will
always be populated,
even in the value
returned from the
main function or
a sub-command function is
the None object.
The length and order of
the return_values will
match those of
opts_previous.

Environment Variables

Environment variables can
be used to override the
default values for
command line options.
To use environment variables
pass a prefix string to
the begin.start() decorator through
the env_prefix parameter:

In the example above,
if an environment variable
MP_NAME existed,
it’s value would be
used as the default for
the name option.
The options value can
still be set by
explicitly passing a
new value as
a command line option.

Configuration files

Configuration files can
also be used to
override the default values of
command line options.
To use configuration files
pass a base file name to
the begin.start() decorator through
the config_file parameter:

This example will
look for configuration files named
.camelot.cfg in
the current directory and/or
the user’s home directory.
A command line option’s
default value can be
changed by an
option value in
a configuration file.
The configuration section
used matches the
decorated function’s name
by default.
This can be changed by
passing a config_section
parameter to begin.start():

In this second example
the section camelot
will be used instead of
a section named run.

Argument type casting

Command line arguments are
always passed as strings.
Sometimes thought it is
more convenient to
receive arguments of
different types.
For example, this is a
possible function for
starting a web application:

Having to convert
the port argument to
an integer and
the debug argument to
a boolean is
additional boilerplate code.
To avoid this begins provides
the begin.convert() decorator.
This decorator accepts functions
as keyword arguments where
the argument name matches that of
the decorator function.
These functions are used
to convert the
types of arguments.

The limitation of using
auto_convert is that
it is not longer possible to
provide additional casting functions.

Command Line Extensions

There are behaviours that
are common to many
command line applications,
such as configuring the
logging and
cgitb modules.
begins provides
function decorators that
extend a program’s
command line arguments to
configure these modules.

begin.tracebacks()

begin.logging()

To use these decorators
they need to decorate
the main function
before begin.start()
is applied.

Tracebacks

The begin.tracebacks() decorator
adds command line options for
extended traceback reports to
be generated for
unhandled exceptions: