Wednesday, December 31, 2014

[logos] AttrDict instance has no key ‘contacts’

The online demo of Lino Logos had caused a traceback:

AttrDict instance has no key 'contacts' (keys are languages, about, users, sessions, bibles, system, comments, lino, contenttypes, humanize, extjs, bootstrap3)

This revealed a subtle problem and inspired me to find a nice solution to it.

The lino.modlib.languages is a small plugin which defines only one menu item into the Configuration menu.

The subtle problem is: into which menu group should the languages plugin integrate? It makes no sense (and is irritating for the user) if such a small plugin creates its own menu group.

I started to write https://www.lino-framework.org/dev/menu.html. For example Introduction to menu groups.

When the languages plugin was written, I “spontaneously” imagined that the Languages table fits into the Contacts menu group. Here is who I wrote this:

def setup_config_menu(site, ui, profile, m):
    m = m.add_menu('contacts', _("Contacts"))
    m.add_action(Languages)

A bit later (when Lino’s plugin system was ready), I changed this to:

def setup_config_menu(site, ui, profile, m):
    p = dd.plugins.contacts
    m = m.add_menu(p.app_label, p.verbose_name)
    m.add_action(Languages)

Now I discovered that this caused a problem in Lino Logos, because Lino Logos has no lino.modlib.contacts installed.

The actual question is: How can the languages plugin know where I want it to be in the menu tree?

The only realistic solution until now was to override setup_menu for both applications.

I would like to avoid this in order to have the languages plugin more “pluggable”.

So I had this idea: I wrote a new plugin method get_menu_group which looks at the lino.core.plugin.Plugin.needed_by attribute. And the lino.modlib.languages plugin is the first usage example. Firstly its models.py specifies:

def setup_config_menu(site, ui, profile, m):
    p = dd.plugins.languages.get_menu_group()
    m = m.add_menu(p.app_label, p.verbose_name)
    m.add_action('languages.Languages')

And secondly, I no longer explicitly yield this plugin in the get_installed_plugins method of Lino Welfare and Lino Logos, but (thirdly) add it to the needs_plugins attribute of lino.modlib.cv and lino_logos.apps.bibles.

Cool! Updated Public demo sites at The Lino framework.