## 6.2.3 Configuration Option Types

There are several option types that should cover just about any type of command-line and configuration option that you may have. However, in the spirit of object-orientedness, you can, of course, subclass one of these and create your own types. `GenericOption` is the base class for all options. It contains all of the underlying framework for options, but should never be instantiated directly. Only subclasses should be instantiated.

class `GenericOption``(` [docsTring, options, default, optional, values, category, callback, synopsis, environ, registry, mandatory, name, source] `)`

  Declare a command line option.

  Instances of subclasses of `GenericOption` must be placed in a `ConfigManager` instance to be used. See the documentation for `ConfigManager` for more details.

  docstring is a string in the format of Python documentation strings that describes the option and its usage. The first line is assumed to be a one-line summary for the option. The following paragraphs are assumed to be a complete description of the option. You can give a paragraph with the label ’Valid Values:’ that contains a short description of the values that are valid for the current option. If this paragraph exists and an error is encountered while validating the option, this paragraph will be printed instead of the somewhat generic error message for that option type.

  options is a string containing all possible variants of the option. All variants should contain the ’-’, ’–’, etc. at the beginning. For boolean options, the option can be preceded by a ’!’ to mean that the option should be turned OFF rather than ON which is the default.

  default is a value for the option to take if it isn’t specified on the command line

  optional is a value for the option if it is given without a value. This is only used for options that normally take a value, but you also want a default that indicates that the option was given without a value.

  values defines valid values for the option. This argument can take the following forms:

  Type&Description
  single value&for `StringOption` this this is a string, for `IntegerOption` this is an integer, for `FloatOption` this is a float. The single value mode is most useful when the value is a regular expression. For example, to specify that a `StringOption` must be a string of characters followed by a digit, ’values’ would be set to `re.compile(r’\w+\d’)`.
  range of values&a two element list can be given to specify the endpoints of a range of valid values. This is probably most useful on `IntegerOption` and `FloatOption`. For example, to specify that an IntegerOption can only take the values from 0 to 10, ’values’ would be set to [0,10]. Note: This mode must always use a Python list since using a tuple means something else entirely.

  tuple of values&a tuple of values can be used to specify a complete list of valid values. For example, to specify that an `IntegerOption` can take the values 1, 2, or 3, ’values’ would be set to `(1,2,3)`. If a string value can only take the values, ’hi’, ’bye’, and any string of characters beginning with the letter ’z’, ’values’ would be set to `(’hi’,’bye’,re.compile(r’z.*?’))`. Note: This mode must *always* use a Python tuple since using a list means something else entirely.

  category is a category key which specifies which category the option belongs to (see the `ConfigManager` documentation on how to create categories).

  callback is a function to call after the value of the option has been validated. This function will be called with the validated option value as its only argument.

  environ is an environment variable to use as default value instead of specified value. If the environment variable exists, it will be used for the default value instead of the specified value.

  registry is a registry key to use as default value instead of specified value. If the registry key exists, it will be used for the default value instead of the specified value. A specified environment variable takes precedence over this value. Note: This is not implemented yet.

  name is a key used to get the option from its corresponding section. You do not need to specify this. It will be set automatically when you put the option into the `ConfigManager` instance.

  mandatory is a flag used to determine if the option itself is required to be present. The idea of a "mandatory option" is a little strange, but I have seen it done.

  source is a flag used to determine whether the option was set directly in the `ConfigManager` instance through Python, by a configuration file/command line option, etc. You do not need to specify this, it will be set automatically during parsing. This flag should have the value of BUILTIN, COMMANDLINE, CONFIGFILE, ENVIRONMENT, REGISTRY, or CODE.

`acceptsArgument``(``)`

  return a boolean indicating whether or not the option accepts an argument on the command-line. For example, boolean options do not accept an argument.

`cast``(`arg`)`

  cast the given value to the appropriate type.

`checkValues``(`value`)`

  check value against all possible valid values for the option. If the value is invalid, raise an `InvalidOptionError` exception.

`clearValue``(``)`

  reset the value of the option as if it had never been set.

`getValue``(`[default]`)`

  return the current value of the option. If default is specified and a value cannot be gotten from any source, it is returned.

`__repr__``(``)`

  return a string containing a command-line representation of the option and its value.

`requiresArgument``(``)`

  return a boolean indicating whether or not the option requires an argument on the command-line.

As mentioned previously, `GenericOption` is an abstract class (i.e. it should not be instantiated directly). Only subclasses of `GenericOption` should be instantiated. Below are some examples of use of some of these subclasses, followed by the descriptions of the subclasses themselves.

       BooleanOption(
          ''' Display help message ''',
          options = '--help -h',
          callback = usage,  # usage() function must exist prior to this
       )

       BooleanOption(
          ''' Set verbosity ''',
          options = '-v --verbose !-q !--quiet',
       )

       StringOption(
          '''
          IP address option

          This option accepts an IP address to connect to.

          Valid Values:
          '#.#.#.#' where # is a number from 1 to 255

          ''',
          options = '--ip-address',
          values = re.compile(r'\d{1,3}(\.\d{1,3}){3}'),
          default = '127.0.0.0',
          synopsis = '#.#.#.#',
          category = 'network',  # Assumes 'network' category exists
       )

       IntegerOption(
          '''
          Number of seconds to wait before timing out

          Valid Values:
          positive integer

          ''',
          options = '--timeout -t',
          default = 300,
          values = [0,1e9],
          category = 'network',
       )

       IntegerOption(
          '''
          Number of tries to connect to the host before giving up

          Valid Values:
          accepts 1, 2, or 3 retries

          ''',
          options = '--tries',
          default = 1,
          values = (1,2,3),
          category = 'network',
       )

       StringOption(
          '''
          Nonsense option for example purposes only

          Valid Values:
          accepts 'hi', 'bye', or any string beginning with the letter 'z'

          ''',
          options = '--nonsense -n',
          default = 'hi',
          values = ('hi', 'bye', re.compile(r'z.*?')),
       )

class `BooleanOption``(`[`GenericOption` arguments]`)`

  Boolean options are simply options that allow you to specify an ‘on’ or ‘off’ state. The accepted values for a boolean option in a config file are ‘on’, ‘off’, ‘true’, ‘false’, ‘yes’, ‘no’, 0, and 1. Boolean options on the command-line do not take an argument; simply specifying the option sets the state to true.

  One interesting feature of boolean options is in specifying the command-line options. Since you cannot specify a value on the command-line (the existence of the option indicates the state), there must be a way to set the state to false. This is done using the ‘not’ operator (!). When specifying the options argument of the constructor, if you prefix an command-line option with an exclamation point, the existence of that option indicates a false state rather than a true state. Below is an example of an options value that has a way to turn debugging information on (--debug) or off (--no-debug).

      BooleanOption( options = '--debug !--no-debug' )

class `CompoundOption``(`[`GenericOption` arguments]`)`

  Compound options are options that contain multiple elements on the command-line. They are simply groups of command-line arguments surrounded by a pair of grouping characters (e.g. ( ), [ ], { }, < >). This grouping can contain anything including other command-line arguments. However, all content between the grouping characters is unparsed. This can be useful if you have a program that wraps another program and you want to be able to forward the wrapped program’s options on. An example of a compound option used on the command-line is shown below.

      # Capture the --diff-opts options to send to another program
      mycommand --other-opt --diff-opts ( -ib --minimal ) file1 file2

class `CountedOption``(`[`GenericOption` arguments]`)`

  A `CountedOption` is a boolean option that keeps track of how many times it has been specified. This is useful for options that control the verbosity of logging messages in a program where the number of times an option is specified, the more logging information is printed.

class `InputDirectoryOption``(`[`GenericOption` arguments]`)`

  An `InputDirectoryOption` is an option that accepts a directory name for input. This directory name is checked to make sure that it exists and that it is readable. If it is not, a `InvalidOptionError` exception is raised.

class `OutputDirectoryOption``(`[`GenericOption` arguments]`)`

  An `OutputDirectoryOption` is an option that accepts a directory name for output. If the directory exists, it is checked to make sure that it is readable. If it does not exist, it is created.

class `InputFileOption``(`[`GenericOption` arguments]`)`

  An `InputFileOption` is an option that accepts a file name for input. The filename is checked to make sure that it exists and is readable. If it isn’t, an `InvalidOptionError` exception is raised.

class `OutputFileOption``(`[`GenericOption` arguments]`)`

  An `OutputFileOption` is an option that accepts a file name for output. If the file exists, it is checked to make sure that it is writable. If a name contains a directory, the path is checked to make sure that it is writable. If the directory does not exist, it is created.

class `FloatOption``(`[`GenericOption` arguments]`)`

  A `FloatOption` is an option that accepts a floating point number.

class `IntegerOption``(`[`GenericOption` arguments]`)`

  An `IntegerOption` is an option that accepts an integer value.

class `MultiOption``(`[`GenericOption` arguments, [delim, range, template]]`)`

  A `MultiOption` is an option that is intended to be used multiple times on the command-line, or take a list of values. Other options when specified more than once simply overwrite the previous value. `MultiOption`s will append the new values to a list.

  The delimiter used to separate multiple values is the comma (,). A different character can be specified in the delim argument.

  In addition, it is possible to specify the number of values that are legal in the range argument. The range argument takes a two element list. The first element is the minimum number of times the argument is required. The second element is the maximum number of times it is required. You can use a ‘*’ (in quotes) to mean an infinite number.

  You can cast each element in the list of values to a particular type by using the template argument. The template argument takes a reference to the option class that you want the values to be converted to.

class `StringOption``(`[`GenericOption` arguments]`)`

  A `StringOption` is an option that accepts an arbitrary string.