Usage

Declaring Flags

Many constant values should be declared as flags. Obtained a NamespaceFlagSet from the GLOBAL_FLAGS singleton GlobalFlagSet object via the namespace() function.

Create namespaced FLAGS object.
from oscar import flag

FLAGS = flag.namespace(__name__)

There should not be a need to create a GlobalFlagSet object manually in typical usage. Flag primitives predefined in the flag module:

class oscar.flag.String(description, default=None, secure=False)[source]

String-valued flag.

class oscar.flag.Int(description, default=None, secure=False)[source]

Integer-valued flag.

class oscar.flag.Float(description, default=None, secure=False)[source]

Float-valued flag.

class oscar.flag.Bool(description, default=None, secure=False)[source]

Boolean-valued flag.

class oscar.flag.List(inner_type, separator, description, default=None, secure=False)[source]

Flag that is a list of another flag type.

These are all constructed with at least a description. default and secure are optional.

Flags must be declared at module level, and can only be declared once. Redefining a flag results in an error.

Example primitive flags.
FLAGS.some_int = flag.Int('some int value')
FLAGS.some_string = flag.String('some string value', 'default string')
FLAGS.some_bool = flag.Bool('secure bool (why?)', secure=True)

Required values are indicated by setting default to REQUIRED.

Required flag example.
FLAGS.required_float = flag.Float('some required float', flag.REQUIRED)

Finally, List is provided which can be used to define a flag which is a list (cannot be polymorphic). It requires two additional arguments: a Var subclass defining the primitive type, and a separator:

List flag example.
FLAGS.int_list = flag.List(flag.Int, ',', 'a list of integer values')

Using flag values in Python

Getting

Flag values can be read directly from the NamespaceFlagSet object (FLAGS above).

Accessing flag values.
FLAGS.some_int = flag.Int('some int value')

print FLAGS.some_int * 10

Setting

Setting is almost the same, but values should be parseable strings, not raw values (since the setter is how the various parsers actually set the values).

>>> FLAGS.some_int = '42'
>>> FLAGS.some_int
42

Positional Arguments

Finally, the flag module may expose positional arguments if a command-line was parsed. These are available via args():

oscar.flag.args()[source]

Return positional args from GLOBAL_FLAGS.

Return type:list[str]

Parsing in __main__

There are three parsers provided, a command-line parser, an environment parser and a parser based on ConfigParser.

oscar.flag.parse_commandline(args)[source]

Parse commandline args with GLOBAL_FLAGS.

oscar.flag.parse_environment(args)[source]

Parse environment args with GLOBAL_FLAGS.

oscar.flag.parse_ini(file_p)[source]

Parse a ConfigParser compatible file with GLOBAL_FLAGS.

Flag parsing must be done explicitly. Each parser can be used independently or with another parser. It is suggested to use the environment parser first followed by the command-line parser, since the environment parser can read SECURED_ settings, and flags can further be overridden by the command line.

Parser Usage.
import os
import sys

from oscar import flag

if __name__ == '__main__':
    flag.parse_environment(os.environ.items())
    flag.parse_commandline(sys.argv[1:])

The ConfigParser parser requires an object providing readline(), which includes a standard opened file.

Note that required flags must be explicitly checked via die_on_missing_required(). If a config file is read, but the path to that config file can be set on the command line, it is useful to refrain from checking if required flags have been set until after the config file is parsed.

Config-file flag.
import os
import sys

from oscar import flag

FLAGS = flag.namespace(__name__)
FLAGS.config_file = flag.String('path to config file')

if __name__ == '__main__':
    flag.parse_commandline(sys.argv[1:])
    if FLAGS.config_file:
        with open(FLAGS.config_file) as config:
            flag.parse_ini(config)
    die_on_missing_required()

Setting Flags from The Outside

Short Names and Full Names

All flags are fully namespaced and are available by referencing them through their module path. For instance, if a flag baz is declared in module foo.bar, it can be referenced on the command line or in the environment through foo.bar.baz.

As a convenience, any uniquely named flag can be referenced on the command line or in the environment through a short name. The short name is for convenience and should not be used in scripts or configuration files. Referencing an ambiguous short name will raise a KeyError.

Environment Variables

If parse_environment() is called on os.environ.items(), environment variables will be mapped onto flags. As noted, the environment parser supports short and full names.

The environment parser will recognize SECURED_SETTING_* environment variables. These are base64 decoded and set on the appropriate flag if present (while also setting the secure attribute on the flag to True).

The environment parser will ignore extraneous environment variables that do not map to a flag.

Note

The last parse method called may overwrite flags set by previous parse methods. It is probably preferable to call parse_environment() before calling parse_commandline().

Command Line

Command-line flags are expected to precede any positional arguments. The presence of a single “–” argument can be used to denote the end of command-line flags. A single “-” or a double “–” are equivalent in denoting a flag. A flag and its value can be separated into separate arguments (i.e. via whitespace on the command line) or a single “=”.

Command-line examples.
# A single '-' is acceptable.
$ ./my_bin.pex -foo=bar
$ ./my_bin.pex -foo bar
# A double '--' is also acceptable.
$ ./my_bin.pex --foo=bar
$ ./my_bin.pex --foo bar
# Everything after '--' becomes a positional argument.
$ ./my_bin.pex -- --foo --bar --baz

Bool flags are special-cased in the command-line parser. A standalone Bool flag with no value indicates True. A Bool flag can only be set explicitly using “=”, and a space between the flag and the value is invalid. Valid boolean values are any case folded variation of yes, true, on, 1 for True, and no, false, off, 0 for False. Other values result in an error.

Boolean special case command-line parsing.
./my_bin.pex --some_bool  # some_bool is set to True
./my_bin.pex --some_bool=False  # some_bool is set to False
./my_bin.pex --some_bool False  # this is invalid and will throw a parse error

Command-line flags also may be referenced by their short name if it’s non-ambiguous, though this is provided as a shortcut for users, and the fully qualified flag name should be used in configuration and scripting.

Finally, if any flags are encountered that do not map to a flag in the application, an error will be raised. All command-line flags must map to a declared flag.

ConfigParser ini files

There is also support for ini files. Sections map to namespaces, and key/value pairs within the sections map to flags within those namespaces.

example.ini
[__main__]
output=output.txt

[utils.zookeeper]
ensemble=zookeeper-1,zookeeper-2,zookeeper-3

The ini parser will need to be ran against a file-like object.

with open('~/.config.ini') as config:
    flag.parse_ini(config)

Finally, every section and key/value within an ini file must map to a namespace and flag. Unexpected sections and keys will raise an error.

Additional Public API for flag

oscar.flag.GLOBAL_FLAGS = <oscar.flag.GlobalFlagSet object>

GlobalFlagSet is a collection of namespaces and flag logic.

GLOBAL_FLAGS.usage

This attribute can be replaced with a function that will print usage (invoked automatically by –help on the command line). The function accepts a single parameter: the GlobalFlagSet object calling it. The default implementation calls GlobalFlagSet.write_flags(). Default value is default_usage().

GLOBAL_FLAGS.usage_long

This attribute can be replaced with a function that will print long usage (invoked automatically by –helplong on the command line). The function accepts a single parameter: the GlobalFlagSet object calling it. The default implementation calls GlobalFlagSet.write_flags_long(). Default value is default_usage_long().

GlobalFlagSet.visit(func)[source]

Walk all set flags, calling func on each.

Parameters:func (F(str, str, Var)) – visiting function
GlobalFlagSet.visit_all(func)[source]

Walk all flags, calling func on each.

Parameters:func (F(str, str, Var)) – visiting function