### Navigation

- index
- modules |
- next |
- previous |
- Basic Structures »

# Global options

The `GlobalOptions` class provides a generic mechanism for setting and accessing global options for parents in one or several related classes, typically for customizing the representation of their elements. This class will eventually also support setting options on a parent by parent basis.

See also

For better examples of `GlobalOptions` in action see `sage.combinat.partition.Partitions.global_options()` and `sage.combinat.tableau.Tableaux.global_options()`.

## Construction of options classes

The general setup for creating a set of global options is:

    MyOptions=GlobalOptions('option name',
        doc='Nice options',
        first_option=dict(default='default value',
                          description='Changes the functionality of _repr_',
                          values=dict(with_bells='causes _repr_ to print with bells',
                                      with_whistles='causes _repr_ to print with whistles',
                                      ...),
                          aliases=dict(bells='option1', whistles='option2', ...),
        second_option=dict(...),
        third_option=dict(),
        end_doc='end of options documentation'
    )

Each option is specified as a dictionary which describes the possible values for the option and its documentation. The possible entries in this dictionary are:

- `alias` – Allows for several option values to do the same thing.
- `alt_name` – An alternative name for this option.
- `checker` – A validation function which returns whether a user supplied value is valid or not. This is typically useful for large lists of legal values such as \(\NN\).
- `default` – Gives the default value for the option.
- `description` – A one line description of the option.
- `link_to` – Links this option to another one in another set of global options. This is used for example to allow `Partitions` and `Tableaux` to share the same `convention` option.
- `setter` – A function which is called after the value of the option is changed.
- `values` – A dictionary assigning each valid value for the option to a short description of what it does.
- `case_sensitive` – (Default: `True`) `True` or `False` depending on whether the values of the option are case sensitive.

For each option, either a complete list of possible values, via `values`, or a validation function, via `checker`, must be given. The values can be quite arbitrary, including user-defined functions which customize the default behaviour of the classes such as the output of `_repr_` or `latex()`. See Dispatchers below, and `dispatcher()`, for more information.

The documentation for the options is automatically constructed by combining the description of each option with a header and footer which are given by the following optional, but recommended, arguments:

- `doc` – The top half of the documentation which appears before the automatically generated list of options and their possible values.
- `end_doc` – The second half of the documentation which appears after the list of options and their values.

The basic structure for defining a `GlobalOptions` class is best illustrated by an example:

    sage: from sage.structure.global_options import GlobalOptions
    sage: menu=GlobalOptions('menu', doc='Fancy documentation\n'+'-'*19, end_doc='The END!',
    ...       entree=dict(default='soup',
    ...                   description='The first course of a meal',
    ...                   values=dict(soup='soup of the day', bread='oven baked'),
    ...                   alias=dict(rye='bread')),
    ...       appetizer=dict(alt_name='entree'),
    ...       main=dict(default='pizza', description='Main meal',
    ...                 values=dict(pizza='thick crust', pasta='penne arrabiata'),
    ...                 case_sensitive=False),
    ...       dessert=dict(default='espresso', description='Dessert',
    ...                    values=dict(espresso='life begins again',
    ...                                cake='waist begins again',
    ...                                cream='fluffy, white stuff')),
    ...       tip=dict(default=10, description='Reward for good service',
    ...       checker=lambda tip: tip in range(0,20))
    ...   )
    sage: menu
    options for menu

For more details see `GlobalOptions`.

## Accessing and setting option values

All options and their values, when they are strings, are forced to be lower case. The values of an options class can be set and accessed by calling the class or by treating the class as an array.

Continuing the example from Construction of options classes:

    sage: menu()
    Current options for menu
      - dessert: espresso
      - entree:  soup
      - main:    pizza
      - tip:     10
    sage: menu('dessert')
    'espresso'
    sage: menu['dessert']
    'espresso'

Note that, provided there is no ambiguity, options and their values can be abbreviated:

    sage: menu['d']
    'espresso'
    sage: menu('m','t',des='esp', ent='sou')  # get and set several values at once
    ['pizza', 10]
    sage: menu(t=15); menu['tip']
    15
    sage: menu(e='s', m='Pi'); menu()
    Current options for menu
      - dessert: espresso
      - entree:  soup
      - main:    pizza
      - tip:     15
    sage: menu(m='P')
    Traceback (most recent call last):
    ...
    ValueError: P is not a valid value for main in the options for menu

## Setter functions

Each option of a `GlobalOptions` can be equipped with an optional setter function which is called after the value of the option is changed. In the following example, setting the option ‘add’ changes the state of the class by setting an attribute in this class using a `classmethod()`. Note that the options object is inserted after the creation of the class in order to access the `classmethod()` as `A.setter`:

    sage: from sage.structure.global_options import GlobalOptions
    sage: class A(SageObject):
    ...       state = 0
    ...       @classmethod
    ...       def setter(cls, option, val):
    ...           cls.state += int(val)
    ...
    sage: A.options=GlobalOptions('A',
    ...                           add=dict(default=1,
    ...                                    checker=lambda v: int(v)>0,
    ...                                    description='An option with a setter',
    ...                                    setter=A.setter))
    sage: a = A(2); a.state
    1
    sage: a.options()
    Current options for A
    - add: 1
    sage: a.options(add=4)
    sage: a.state
    5
    sage: a.options()
    Current options for A
    - add: 4

Another alternative is to construct the options class inside the `__init__` method of the class `A`.

## Documentation for options

The documentation for a `GlobalOptions` is automatically generated from the supplied options. For example, the generated documentation for the options `menu` defined in Construction of options classes is the following:

    Fancy documentation
    -------------------

    OPTIONS:

    - ``appetizer`` -- alternative name for ``entree``

    - ``dessert`` -- (default: ``espresso``)
      Dessert

      - ``cake``     -- waist begins again
      - ``cream``    -- fluffy, white stuff
      - ``espresso`` -- life begins again

    - ``entree`` -- (default: ``soup``)
      The first course of a meal

      - ``bread`` -- oven baked
      - ``rye``   -- alias for bread
      - ``soup``  -- soup of the day

    - ``main`` -- (default: ``pizza``)
      Main meal

      - ``pasta`` -- penne arrabiata
      - ``pizza`` -- thick crust

    - tip -- (default: 10)
      Reward for good service

    The END!

    See :class:`~sage.structure.global_options.GlobalOptions` for more features of these options.

In addition, help on each option, and its list of possible values, can be obtained by (trying to) set the option equal to ‘?’:

    sage: menu(des='?')
    - ``dessert`` -- (default: ``espresso``)
      Dessert
    <BLANKLINE>
      - ``cake``     -- waist begins again
      - ``cream``    -- fluffy, white stuff
      - ``espresso`` -- life begins again
    <BLANKLINE>
    Current value: espresso

## Dispatchers

The whole idea of a `GlobalOptions` class is that the options change the default behaviour of the associated classes. This can be done either by simply checking what the current value of the relevant option is. Another possibility is to use the options class as a dispatcher to associated methods. To use the dispatcher feature of a `GlobalOptions` class it is necessary to implement separate methods for each value of the option where the naming convention for these methods is that they start with a common prefix and finish with the value of the option.

If the value of a dispatchable option is set equal to a (user defined) function then this function is called instead of a class method.

For example, the options `MyOptions` can be used to dispatch the `_repr_` method of the associated class `MyClass` as follows:

    class MyClass(...):
        global_options=MyOptions
        def _repr_(self):
            return self.global_options.dispatch(self,'_repr_','first_option')
        def _repr_with_bells(self):
            print 'Bell!'
        def _repr_with_whistles(self):
            print 'Whistles!'

In this example, `first_option` is an option of `MyOptions` which takes values `bells`, `whistles`, and so on. Note that it is necessary to make `self`, which is an instance of `MyClass`, an argument of the dispatcher because `dispatch()` is a method of `GlobalOptions` and not a method of `MyClass`. Apart from `MyOptions`, as it is a method of this class, the arguments are the attached class (here `MyClass`), the prefix of the method of `MyClass` being dispatched, the option of `MyOptions` which controls the dispatching. All other arguments are passed through to the corresponding methods of `MyClass`. In general, a dispatcher is invoked as:

    self.options.dispatch(self, dispatch_to, option, *args, **kargs)

Usually this will result in the method `dispatch_to + '_' + MyOptions(options)` of `self` being called with arguments `*args` and `**kargs` (if `dispatch_to[-1] == '_'` then the method `dispatch_to + MyOptions(options)` is called).

If `MyOptions(options)` is itself a function then the dispatcher will call this function instead. In this way, it is possible to allow the user to customise the default behaviour of this method. See `dispatch()` for an example of how this can be achieved.

The dispatching capabilities of `GlobalOptions` allows options to be applied automatically without needing to parse different values of the option (the cost is that there must be a method for each value). The dispatching capabilities can also be used to make one option control several methods:

    def __le__(self, other):
        return self.options.dispatch(self, '_le_','cmp', other)
    def __ge__(self, other):
        return self.options.dispatch(self, '_ge_','cmp', other)
    def _le_option_a(self, other):
        return ...
    def _ge_option_a(self, other):
        return ...
    def _le_option_b(self, other):
        return ...
    def _ge_option_b(self, other):
        return ...

See `dispatch()` for more details.

## Doc testing

All of the options and their effects should be doc-tested. However, in order not to break other tests, all options should be returned to their default state at the end of each test. To make this easier, every `GlobalOptions` class has a `reset()` method for doing exactly this.

## Tests

TESTS:

As options classes to not know how they are created they cannot be pickled:

    sage: menu=GlobalOptions('menu', doc='Fancy documentation\n'+'-'*19, end_doc='The END!',
    ...       entree=dict(default='soup',
    ...                   description='The first course of a meal',
    ...                   values=dict(soup='soup of the day', bread='oven baked'),
    ...                   alias=dict(rye='bread')),
    ...       appetizer=dict(alt_name='entree'),
    ...       main=dict(default='pizza', description='Main meal',
    ...                 values=dict(pizza='thick crust', pasta='penne arrabiata'),
    ...                 case_sensitive=False),
    ...       dessert=dict(default='espresso', description='Dessert',
    ...                    values=dict(espresso='life begins again',
    ...                                cake='waist begins again',
    ...                                cream='fluffy, white stuff')),
    ...       tip=dict(default=10, description='Reward for good service',
    ...       checker=lambda tip: tip in range(0,20))
    ...   )
    sage: TestSuite(menu).run(skip='_test_pickling')

Warning

Default values for `GlobalOptions` can be automatically overridden by calling the individual instances of the `GlobalOptions` class inside `$HOME/.sage/init.sage`. However, this needs to be disabled by developers when they are writing or checking doc-tests. Another possibly would be to `reset()` all options before and after all doct-tests which are dependent on particular values of options.

AUTHORS:

- Andrew Mathas (2013): initial version

class `sage.structure.global_options.``GlobalOptions`(name, doc='', end_doc='', **options)

  Bases: `sage.structure.sage_object.SageObject`

  The `GlobalOptions` class is a generic class for setting and accessing global options for `sage` objects. It takes as inputs a `name` for the collection of options and a dictionary of dictionaries which specifies the individual options. The allowed/expected keys in the dictionary are the following:

  INPUTS:

  - `name` – Specifies a name for the options class (required)
  - `doc` – Initial documentation string
  - `end_doc` – Final documentation string
  - `<options>=dict(...)` – Dictionary specifying an option

  The options are specified by keyword arguments with their values being a dictionary which describes the option. The allowed/expected keys in the dictionary are:

  - `alias` – Defines alias/synonym for option values
  - `alt_name` – Alternative name for an option
  - `checker` – A function for checking whether a particular value for the option is valid
  - `default` – The default value of the option
  - `description` – Documentation string
  - `link_to` – Links to an option for this set of options to an option in another `GlobalOptions`
  - `setter` – A function (class method) which is called whenever this option changes
  - `values` – A dictionary of the legal values for this option (this automatically defines the corresponding `checker`). This dictionary gives the possible options, as keys, together with a brief description of them.
  - `case_sensitive` – (Default: `True`) `True` or `False` depending on whether the values of the option are case sensitive.

  Options and their values can be abbreviated provided that this abbreviation is a prefix of a unique option.

  Calling the options with no arguments results in the list of current options being printed.

  EXAMPLES:

      sage: from sage.structure.global_options import GlobalOptions
      sage: menu=GlobalOptions('menu', doc='Fancy documentation\n'+'-'*19, end_doc='End of Fancy documentation',
      ...       entree=dict(default='soup',
      ...                   description='The first course of a meal',
      ...                   values=dict(soup='soup of the day', bread='oven baked'),
      ...                   alias=dict(rye='bread')),
      ...       appetizer=dict(alt_name='entree'),
      ...       main=dict(default='pizza', description='Main meal',
      ...                 values=dict(pizza='thick crust', pasta='penne arrabiata'),
      ...                 case_sensitive=False),
      ...       dessert=dict(default='espresso', description='Dessert',
      ...                    values=dict(espresso='life begins again',
      ...                                cake='waist begins again',
      ...                                cream='fluffy white stuff')),
      ...       tip=dict(default=10, description='Reward for good service',
      ...                checker=lambda tip: tip in range(0,20))
      ...   )
      sage: menu
      options for menu
      sage: menu(entree='s')         # unambiguous abbreviations are allowed
      sage: menu(t=15);
      sage: (menu['tip'], menu('t'))
      (15, 15)
      sage: menu()
      Current options for menu
        - dessert: espresso
        - entree:  soup
        - main:    pizza
        - tip:     15
      sage: menu.reset(); menu()
      Current options for menu
        - dessert: espresso
        - entree:  soup
        - main:    pizza
        - tip:     10
      sage: menu['tip']=40
      Traceback (most recent call last):
      ...
      ValueError: 40 is not a valid value for tip in the options for menu
      sage: menu(m='p')           # ambiguous abbreviations are not allowed
      Traceback (most recent call last):
      ...
      ValueError: p is not a valid value for main in the options for menu

  The documentation for the options class is automatically generated from the information which specifies the options:

      Fancy documentation
      -------------------

      OPTIONS:

      - dessert:  (default: espresso)
        Dessert

        - ``cake``     -- waist begins again
        - ``cream``    -- fluffy white stuff
        - ``espresso`` -- life begins again

      - entree:  (default: soup)
        The first course of a meal

        - ``bread`` -- oven baked
        - ``rye``   -- alias for bread
        - ``soup``  -- soup of the day

      - main:  (default: pizza)
        Main meal

        - ``pasta`` -- penne arrabiata
        - ``pizza`` -- thick crust

      - tip:  (default: 10)
        Reward for good service

      End of Fancy documentation

      See :class:`~sage.structure.global_options.GlobalOptions` for more features of these options.

  The possible values for an individual option can be obtained by (trying to) set it equal to ‘?’:

      sage: menu(des='?')
      - ``dessert`` -- (default: ``espresso``)
        Dessert
      <BLANKLINE>
        - ``cake``     -- waist begins again
        - ``cream``    -- fluffy white stuff
        - ``espresso`` -- life begins again
      <BLANKLINE>
      Current value: espresso

  `default_value`(option)

    Return the default value of the option.

    EXAMPLES:

        sage: from sage.structure.global_options import GlobalOptions
        sage: FoodOptions=GlobalOptions('daily meal',
        ...         food=dict(default='apple', values=dict(apple='a fruit',pair='of what?')),
        ...         drink=dict(default='water', values=dict(water='a drink',wine='a lifestyle')))
        sage: FoodOptions.default_value('food')
        'apple'

  `dispatch`(obj, dispatch_to, option, *args, **kargs)

    Todo

    title

    The dispatchable options are options which dispatch related methods of the corresponding class - or user defined methods which are passed to `GlobalOptions`. The format for specifying a dispatchable option is to include `dispatch_to = <option name>` in the specifications for the options and then to add the options to the (element) class. Each option is then assumed to be a method of the element class with a name of the form `<option name> + '_' + <current vale for this option'`. These options are called by the element class via:

        return self.options.dispatch(self, dispatch_to, option, *args, **kargs)

    Note that the argument `self` is necessary here because the dispatcher is a method of the options class and not of `self`. The value of the option can also be set to a user-defined function, with arguments `self` and `option`; in this case the user’s function is called instead.

    EXAMPLES:

    Here is a contrived example:

        sage: from sage.structure.global_options import GlobalOptions
        sage: DelimitedListOptions=GlobalOptions('list delimiters',
        ...             delim=dict(default='b', values={'b':'brackets', 'p':'parentheses'}))
        sage: class DelimitedList(CombinatorialObject):
        ...      options=DelimitedListOptions
        ...      def _repr_b(self): return '[%s]' % ','.join('%s'%i for i in self._list)
        ...      def _repr_p(self): return '(%s)' % ','.join('%s'%i for i in self._list)
        ...      def _repr_(self): return self.options.dispatch(self, '_repr_','delim')
        sage: dlist=DelimitedList([1,2,3]); dlist
        [1,2,3]
        sage: dlist.options(delim='p'); dlist
        (1,2,3)
        sage: dlist.options(delim=lambda self: '<%s>' % ','.join('%s'%i for i in self._list)); dlist
        <1,2,3>

  `reset`(option=None)

    Reset options to their default value.

    INPUT:

    - `option` – (Default: `None`) The name of an option as a string or `None`. If `option` is specified only this option is reset to its default value; otherwise all options are reset.

    EXAMPLES:

        sage: from sage.structure.global_options import GlobalOptions
        sage: opts=GlobalOptions('daily meal',
        ...      food=dict(default='bread', values=dict(bread='rye bread', salmon='a fish')),
        ...      drink=dict(default='water',values=dict(water='essential for life',wine='essential')))
        sage: opts(food='salmon'); opts()
        Current options for daily meal
          - drink: water
          - food:  salmon
        sage: opts.reset('drink'); opts()
        Current options for daily meal
          - drink: water
          - food:  salmon
        sage: opts.reset(); opts()
        Current options for daily meal
          - drink: water
          - food:  bread

### Navigation

- index
- modules |
- next |
- previous |
- Basic Structures »