Advanced

Mutliple Files

You can split up your menu files into multiple Python files. This is useful if you have lots of menus, or the menu actions are complex.

One example layout like so:

| main.py
| build_menu.py
| test_menu.py

main.py:

import build_menu
import test_menu
import climenu

if __name__ == '__main__':
    climenu.run()

build_menu.py

import climenu

@climenu.group(title='Build Menu')
def build_menu(): pass

@build_menu.menu(title='Build package')
def build_package():
    pass

@build_menu.menu(title='Build release')
def build_release():
    pass

test_menu.py

import climenu

@climenu.group(title='Test Menu')
def test_menu(): pass

@test_menu.menu(title='Run test #1')
def test_one():
    pass

@test_menu.menu(title='Run test #2')
def test_two():
    pass

Dynamic Menu Items

A MenuGroup is made up of Menu items. Normally, you create these menu items using the @climenu.menu decorator. However, sometimes you don’t know what these items should be until runtime.

In this case, you can use the items_getter, items_getter_args, and items_getter_kwargs parameters to the @group decorator.

items_getter is a callback function that returns a list of tuples in the form (<item-title>, <callback-function>). If this function takes arguments, you’ll need to also use some combination of items_getter_args (a list of arguments to pass to the callback function) and items_getter_kwargs (a dictionary of keyword arguments).

Note

You will need to use functools.partial() if the function(s) you are returning from items_getter takes any arguments. See example below.

dynamic-group.py

from functools import partial
import climenu


def print_var(variable):
    '''print the variable'''
    print(str(variable))


def build_items(count):
    # In this example, we're generating menu items based on some
    # thing that's determined at runtime (e.g. files in a directory).

    # For this case, we're simply using `xrange` to generate a range of
    # items.  The function that eventually gets called takes 1 argument.
    # Therefore, we need to use ``partial`` to pass in those arguments at
    # runtime.

    items = []
    for index in xrange(count):
        items.append(
            (
                'Run item %i' % (index + 1),
                partial(print_var, 'Item %i' % (index + 1))
            )
        )

    return items

@climenu.menu(title='Do the first thing')
def first_thing():
    # A simple menu item
    print('Did the first thing!')


@climenu.group(items_getter=build_items, items_getter_kwargs={'count': 7})
def build_group():
    '''A dynamic menu'''
    # This is just a placeholder for a MenuGroup.  The items in the menu
    # will be dymanically generated when this module loads by calling
    # `build_items`.
    pass


if __name__ == '__main__':
    climenu.run()