pythonfunctional-programmingconfiguration-files

What are my options for configuration files that contain a function in python?


I'm creating a chat bot manager in python, where myself (or other developers) can provide a configuration file to the manager and it will generate a bot depending on what it found in the config.

The chat bot manager is generally for monitoring different services, and then performing some sort of action depending on what it finds while monitoring. Ideally, I'd have something that looks like the following:

[
  {
    triggerURL: "www.foobar.com/some/health/check",
    triggerMethod: "GET"
    healthyStatusCodes: [200, 202],
    healthyResponseBody: "{\"status\":\"ok\"}",
    healthyCallback: () => console.log("do something here"),
    unhealthyCallback: () => console.log("do something else here")
  }
]

You might notice my example is a little JS-esque.

Is there a way I can embed javascript into a python program to accomplish what I want?

Are there any other alternatives that do something similar? I'd like to keep the amount of clutter in the configuration file to a minimum, and would like to avoid future developers needing to write any extra code to get it working.


Solution

  • The simplest is to keep it as Python's file with Python's dictionary.
    It can keep Python's functions too.

    You can assign callback (function's name without ()) or you can use lambda

    my_config.py

    def other_function():
        print("do something else here")
    
    config = {
        "triggerURL": "www.foobar.com/some/health/check",
        "triggerMethod": "GET",
        "healthyStatusCodes": [200, 202],
        "healthyResponseBody": {"status": "ok"},
        "healthyCallback": lambda: print("do something here"),
        "unhealthyCallback": other_function,
    }
    

    And in main code you can do

    import my_config
    
    print(my_config.config["triggerURL"])
    my_config.config["healthyCallback"]()
    

    You may also use module importlib to use strings for import.

    import importlib
    
    my_config = importlib.import_module('my_config')
    
    print(my_config.config["triggerURL"])
    my_config.config["healthyCallback"]()
    

    If you have file in subfolder other/my_config.py then you can use other.my_config

    importlib.import_module('other.my_config')
    

    So you could use os.listdir() to get all files in folder or subfolder and import them.

    import importlib
    import os
    
    configs = {}
    
    for name in os.listdir('other'):
        if name.endswith('.py') and not name.startswith('_'):  # skip __pycache__.py
            name = name[:-3]  # skip extension .py
            configs[f'other.{name}'] = importlib.import_module(f'other.{name}')
    
    # --- single config ---
    
    print(configs['other.my_config'].config["triggerURL"])
    configs['other.my_config'].config["healthyCallback"]()   
    
    # --- or all configs at once ---
    
    for name in configs:
        print('name:', name)
        print(configs[name].config["triggerURL"])
        configs[name].config["healthyCallback"]()