Organizing your config.yaml

Location of config.yaml

The base yamjam config file is located ~/.yamjam/config.yaml

  • on windows:

    c:\documents and settings\[username]\.yamjam\config.yaml

  • on unix:

    ~/.yamjam/config.yaml

Then yamjam looks for possible overrides/additions in the current working directory of the APP for a file named config.yaml (if it exists) This would be the project config.yaml

You can override the config file(s) when you call the function by specifying a different one explicitly. i.e.

cfg = yamjam('/path/to/file/file')

By default YamJam looks for two config.yaml files, the base and then a project specific one. You may specify one or more files. Each file path listed should be separated by semi-colons(;) NOTE: if you specify files, YamJam then only looks for them and not the default base and project files.

cfg = yamjam('/path/to/file/file1;/other/path/file2')

Django Specific

In a Django environment, placing a config.yaml in the same directory as your settings.py file is the way to go, if needed. yamjam will look for the base config in ~/.yamjam/config.yaml and a project one in the directory where your settings.py file is located, by default.

settings.py

from YamJam import yamjam
...

CFG = yamjam()['myproject']

...

Then your config information from yamjam will be available any place you import settings.

from django.conf import settings

settings.CFG            # your yamjam values

Base config only

The vast majority of use cases can be accomplished with just a base config located at ~/.yamjam/config.yaml

Be hesitant to implement a project level config.yaml until you hit an edge case that requires it. This is the primary way of using YamJam. The project level config.yaml and user specified locations cause as many problems as the solve and or only applicable to a small set of edge cases. You will be best served by not straying from the KISS principle.

Structure of config.yaml

config.yaml is a straight up yaml file. See http://pyyaml.org/ and http://www.yaml.org/ for advanced usage. However, if you write python you know what you need to write decent yaml. White space is relevant and that is a good thing! What makes Python a joy to read is the same for yaml.

Single YAML document. A yaml file can contain multiple documents. YamJam will only evaluate the first document. Use namespace in the document to logically divide setting for multiple projects.

By default, Yamjam uses yaml’s safe_load directive to read the config file. This is for safety and sanity. If you find yourself wanting to store a custom python object in your config.yaml, you’ll want to re-evaluate your storage. We do leave the keys in the ignition and you can override .safe_load with .load by calling yamjam with the safe=False parameter. Missing toes from foot shooting is always the users responsibility.

Example

if you edit your ~/.yamjam/config.yaml file to include

myproject:
    key1: value
    key2: 42

It is returned from yamjam() as a dictionary.

{'myproject':
    {'key1': 'value',
     'key2': 42
    }
}

to get the value of key2, under myproject

>>> yamjam()['myproject']['key2']
42

Ok, now you know how to set up a dictionary in yaml, here is how you set up a list for a value.

edit config.yaml

myproject:
    key1: value
    key2: [42, 21, 7]

Now the value of key2 will return a list with 3 integers.

>>> yamjam()['myproject']['key2']
[42, 21, 7]

Now you are truly dangerous. You can create a dictionary of dictionaries that can contain more dictionaries, lists, integers, floats, strings, etc.

In fact yaml and pyyaml can do some wonderfully advanced stuff. But, always tend to the simplest form that will get the job done, think DRY KISS.

yjlint - linting for your config.yaml

When you installed YamJam, it created a console script yjlint that you can run from the command line to check your config.yaml files. To lint your config file:

yjlint ~/.yamjam/config.yaml

This will report any problems with the YAML in a config.yaml file.

If there is a YAML formatting error with any of your specified files, yamjam() will raise a YAMLError. You can of course, wrap your call to yamjam() with a try / except block.

from YamJam import yamjam, YAMLError
try:
    cfg = yamjam()
Except YAMLError:
    die_gracefully()

Use yjlint to make sure the YAML in your config is well formatted.

Logical Alignment

Since your config.yaml can store settings for more than one project and it almost always will, the standard use case is to create a section named for the project that uses it. i.e. If you have a Django project named ‘myproject’ then create a section in your config.yaml named myproject.

myproject:
    django-secret-key: my-secret-key

Ok, now you will need database connection information. So let’s add it.

myproject:
    django-secret-key: my-secret-key
    database:
        engine: django.db.backends.postgresql_psycopg2
        name: mydatabase
        user: mydatabaseuser
        password: mypassword
        host: 127.0.0.1
        port: 5432

Now let’s create config settings for our next-project

myproject:
    django-secret-key: my-secret-key
    database:
        engine: django.db.backends.postgresql_psycopg2
        name: mydatabase
        user: mydatabaseuser
        password: mypassword
        host: 127.0.0.1
        port: 5432

next-project:
    django-secret-key: next-project-secret-key
    database:
        engine: django.db.backends.postgresql_psycopg2
        name: mynextdatabase
        user: mynextdatabaseuser
        password: mynextpassword
        host: 127.0.0.1
        port: 5432

Ok, let’s access the django-secret-key for next-project

>>> yamjam()['next-project']['django-secret-key']
next-project-secret-key

So, now you can start factoring out your sensitive data from your app. One more thing, in case it is not obvious, you can reduce your typing by caching just the config information you need to access.

>>> cfg = yamjam()['next-project']
>>> cfg['django-secret-key']
next-project-secret-key

That will keep your code looking clean and also, you just cached the results of the yamjam() call. Further accesses to cfg now happen at break-neck python speed.

Each time your call yamjam() it re-reads the config files. Sometimes this is desired, sometimes not but as a programmer you have complete and simple control over how things happen.

Merging Config Data

When more than one config.yaml is processed, base and project are merged using the following 2 rules.

If the value being merged is not a dictionary then the base value is replaced by the project.

{‘key1’: val1} merged with {‘key1’: val2} results in {‘key1’: val2}

If the value being merged is a dictionary, then it is merged.

{‘key1’: {‘foo’: 2}} merged with {‘key1’: {‘bar’: 3}} results in {‘key1’: {‘foo’: 2, ‘bar’: 3}}

and

{‘key1’: {‘foo’: 2}} merged with {} results in {‘key1’: {‘foo’: 2}}

This way the project config only specified overrides and additions to the base config. See the tests for test_merge.py for more examples. But the net result of the merge should not surprise you and allow for you to supply the minimal amount of project config data needed to modify the base config.