Quickstart

This quickstart provides a short introduction on how to get started with ResConfig. Read Installation first, if you have not installed the resconfig package.

Let us first create an ResConfig object with a simple default configuration for your application, myapp.py:

from resconfig ResConfig

config = ResConfig({"db": {"host": "localhost", "port": 5432}})

By default, ResConfig loads configuration immediately after its initialization. To control the timing of load, use the load_on_init flag:

config = ResConfig({"db": {"host": "localhost", "port": 5432}},
                   load_on_init=False)
config.load()

The following sections introduce you to the basic usage of ResConfig object.

The “.”-Style Key Notation

ResConfig exposes dict-like interface for value access but additionally allows the “.”-style notation for nested keys. The following methods all return the same value, localhost:

host = config["db"]["host"]
host = config["db.host"]
host = config.get("db.host")  # similar to dict.get

The “.”-style can be used elsewhere, e.g.,

config = ResConfig({"db.host": "localhost", "db.port": 5432})

This will be the same default configuration shown earlier. ResConfig takes care of nesting the dict for you.

Use with Configuration Files

To read configuration from (multiple) files, supply a list of paths on object initialization:

config = ResConfig({"db.host": "localhost", "db.port": 5432},
                   config_files=["myconf.yml",
                                 "~/.myconf.yml,
                                 "/etc/myconf.yml"])

If any of the files exists, they are read in the reverse order, i.e., /etc/myconf.yml, ~/.myconf.yml, and then myconf.yml, and the configuration read from them get merged in that order, overriding the default. This allows layered configuration based on specificity by filesystem location. Read Configuration from Files for more detail.

Use with Environment Variables

Properly named environment variables can override default configuration. When you run your myapp.py app with the DB_HOST and/or DB_PORT environment variables set, their values override the default:

$ DB_HOST=remotehost DB_PORT=3306 python myapp.py

That is, config["db.host"] and config["db.port"] will return remotehost and 3306, respectively. As a rule of thumb, a configuration key maps to an uppercased, “_”-delimited (when nested) environment variable name. Read Environment Variables for more detail.

Use with ArgumentParser

A ResConfig object can dynamically generate ArgumentParser arguments from default configuration:

parser = argparse.ArgumentParser()
parser.add_argument(...)  # Define other arguments

config.add_arguments_to_argparse(parser)
# --pg-host and --pg-port arguments are now available

After actually parsing the (command-line) arguments, pass the parse result to ResConfig and then load the configuration:

args = parser.parse_args()
config.prepare_from_argparse(args)
config.load()

For more detail, read ArgumentParser Integration.

Adding Actions on Changes

A ResConfig object is aware of changes to its configuration. Watch functions watch changes happening at any nested key to act on them:

from resconfig import Action

@config.watch("db.host")
def act_on_nested_key(action, old, new):
    if action == Action.ADDED:
        # db.host added
    elif action == Action.MODIFIED:
        # db.host modified
    elif action == Action.RELOADED:
        # db.host reloaded
    elif action == Action.REMOVED:
        # db.host removed

Here, the act_on_nested_key() function is called whenever configuration changes occur at db.host and can decide what to do with the old and/or new values. For more detail, read Watch Functions.