summaryrefslogtreecommitdiff
path: root/postgresqleu/confreg/contextutil.py
blob: a0f7e480810dd34a4b1a1ebd7f2baf849d4eccfd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
import os
import json
import logging
import copy


# XXX: keep in sync with deploystatic.py!
def deep_update_context(target, source):
    for k, v in source.items():
        if type(v) == dict:
            # If this is a dict stored in the dict
            if k not in target:
                # Target didn't have it, so copy it over
                target[k] = copy.deepcopy(v)
            elif type(target[k]) != dict:
                # Target had something but it's not a dict, so overwrite it
                target[k] = copy.deepcopy(v)
            else:
                deep_update_context(target[k], v)
        else:
            target[k] = copy.copy(v)


def _load_context_file(filename):
    try:
        with open(filename, encoding='utf8') as f:
            return json.load(f)
    except ValueError as e:
        # Malformatted JSON -- pass it through as an exception
        raise
    except Exception:
        # Any other error, just ignore it (?)
        return {}


def load_base_context(rootdir):
    if os.path.isfile(os.path.join(rootdir, 'templates/context.json')):
        return _load_context_file(os.path.join(rootdir, 'templates/context.json'))
    return {}


def load_override_context(rootdir):
    # Load contexts in override directory, if any
    c = {}
    if os.path.isdir(os.path.join(rootdir, 'templates/context.override.d')):
        for fn in sorted(os.listdir(os.path.join(rootdir, 'templates/context.override.d'))):
            if fn.endswith('.json'):
                try:
                    with open(os.path.join(rootdir, 'templates/context.override.d', fn)) as f:
                        deep_update_context(c, json.load(f))
                except Exception as e:
                    logging.getLogger(__name__).warning(
                        'Failed to load context file {}: {}'.format(os.path.join(rootdir, 'templates/context.override.d', fn), e)
                    )
    return c


def update_with_override_context(context, rootdir):
    deep_update_context(context, load_override_context(rootdir))