errbotio / errbot

Errbot is a chatbot, a daemon that connects to your favorite chat service and bring your tools and some fun into the conversation.
http://errbot.io
GNU General Public License v3.0
3.12k stars 614 forks source link

Need help with get_configuration_template #1512

Closed kennedy closed 8 months ago

kennedy commented 3 years ago

In order to let us help you better, please fill out the following fields as best you can:

I am...

I am running...

Issue description

I am attempting to use get_configuration_template to load a json file as self.config using this documentation

import json
from pprint import pprint

from errbot import BotPlugin

class PluginExample(BotPlugin):
    def get_configuration_template(self):
        return json.load(open('config/properties.json'))

    def activate(self, *args, **kwargs) -> None:
        super(self.__class__, self).activate(*args, **kwargs)
        pprint(self.config)  # None
// ./config/properties.json
{
  "config_item_1": "data_1",
  "config_item_2": "data_2",
  "config_item_3": "data_3",
  "config_item_4": {
    "sub_item_1": 124145
  },
  "config_list_1": [
    "test",
    "list"
  ]
}

But my self.config object is still none. I stepped through the stack trace and this method gets called and returned, but it still shows up as None.

Steps to reproduce

I created a simple plugin below and ran the debugger. The output from the pprint(self.config) is None

import json
from pprint import pprint

from errbot import BotPlugin

class PluginExample(BotPlugin):
    def get_configuration_template(self):
        return json.load(open('config/properties.json'))

    def activate(self, *args, **kwargs) -> None:
        super(self.__class__, self).activate(*args, **kwargs)
        pprint(self.config)  # None

Additional info

If you have any more information, please specify it here.

nzlosh commented 2 years ago

This issue is probably no longer relevant for the original poster but I'm responding here in case others come across this issue.

As per the documentation https://errbot.readthedocs.io/en/latest/user_guide/plugin_development/configuration.html#plugin-configuration-through-the-built-in-config-command self.config is None when errbot starts and the plugin has not been configured via bot command.

The config template values are not applied automatically to the plugin, they are shown when the !plugin config <plugin> command is called. It is only when the !plugin config <plugin> <config_data> command is run that the config values are set within the plugin and will be persisted in the data store.

To provide default values that can be overridden by the bot command, it would be possible to set a global variable in the plugin and conditionally set self.config when the plugin is activated.

DEFAULT_CONFIG = json.load(open('config/properties.json'))

class PluginExample(BotPlugin):
    def get_configuration_template(self):
        return DEFAULT_CONFIG

    def activate(self, *args, **kwargs) -> None:
        super(self.__class__, self).activate(*args, **kwargs)
        if self.config is None:
            self.config = {}
            self.config.update(DEFAULT_CONFIG)
kennedy commented 2 years ago

@nzlosh This is actually still relevant, thank you for responding.

I did not correlate the !plugin config command to the get_configuration_template() method, I appreciate you clarifying that critical detail. My bot does not use the !plugin to load the plugin, would updating the self.config dictionary in the activate() method be the recommended best practice in loading persistent external data?

nzlosh commented 2 years ago

Based on the documentation, I don't think it would be considered best practice. It was more to demonstrate how the configuration could be set before the user invokes the !config plugin command. Following the documentation, you wouldn't alter the self.config object, but write plugin configuration to self because the plugin is the store https://errbot.readthedocs.io/en/latest/user_guide/plugin_development/persistence.html.

If the use case isn't for the plugin developer to provide sane defaults, but allow the system administrator to set sane default, then errbot can be invoked from the command line to get/set plugin values using:

  --storage-set STORAGE_SET
                        DANGER: Delete the given storage namespace and set the python dictionary expression passed on stdin.
  --storage-merge STORAGE_MERGE
                        DANGER: Merge in the python dictionary expression passed on stdin into the given storage namespace.
  --storage-get STORAGE_GET
                        Dump the given storage namespace in a format compatible for --storage-set and --storage-merge.

The way configuration is stored was done this way so that the bot could be administered completely from chat.

This is not the only way one can develop a plugin, you can read configuration set in config.py through self.bot_config. This would make configuration immutable to users and bot admin. You could fetch config from outside the machine e.g. from a web server or a database server which might mean the plugin is configured at an organisational level.