Example usage

Using fields

Your first step should be defining configuration schema:

import logging
import glorpen.config.fields.simple as f
from glorpen.config.fields.log import LogLevel

project_path = "/tmp/project"

spec = f.Dict({
  "project_path": f.Path(default=project_path),
  "project_cache_path": f.Path(default="{{ project_path }}/cache"),
  "logging": fl.LogLevel(default=logging.INFO),
  "database": f.String(),
  "sources": f.Dict({
      "some_param": f.String(),
      "some_path": f.Path(),
  }),
  "maybe_string": f.Variant([
      f.String(),
      f.Number()
  ])
})

Example yaml config:

logging: "DEBUG"
database: "mysql://...."
sources:
  some_param: "some param"
  some_path: "/tmp"
maybe_string: 12

Then you can create glorpen.config.Config instance:

from glorpen.config import Config
import glorpen.config.loaders as loaders

loader = loaders.YamlLoader(filepath=config_path)
cfg = Config(loader=loader, spec=spec).finalize()

cfg.get("sources.some_param") #=> 'some param'
cfg.get("project_path") #=> '/tmp/project'
cfg.get("project_cache_path") #=> '/tmp/project/cache'
cfg.get("logging") #=> 10
cfg.get("maybe_string") #=> 12

Creating custom fields

Custom field class should extend glorpen.config.fields.base.Field or glorpen.config.fields.base.FieldWithDefault.

glorpen.config.fields.base.Field.make_resolvable() method should register normalizer functions which later will be called in registration order. Each value returned by normalizer is passed to next one. After chain end value is returned as config value.

Returned glorpen.config.fields.base.ResolvableObject instance is resolved before passing it to next normalizer.

If value passed to normalizator is invalid it should raise glorpen.config.exceptions.ValidationError. Sometimes value can be lazy loaded - it is represented as glorpen.config.fields.base.ResolvableObject. You can get real value by using glorpen.config.fields.base.resolve().

class MyValue(object):
   def __init__(self, value):
      super(MyValue, self).__init__()
      self.value = value

class MyField(Field):

    def to_my_value(self, value, config):
        return MyValue(value)

    def is_value_supported(self, value):
        return True

    def make_resolvable(self, r):
        r.on_resolve(self.to_my_value)

The last thing is to use prepared custom field in configuration spec.