Project

General

Profile

Download (2.36 KB) Statistics
| Branch: | Revision:
1
#!/usr/bin/env python
2
#
3
# Copyright (c) 2012 Cabo A/S
4
# All rights reserved.
5
#
6
# Written by Dan Villiom Podlaski Christiansen <dan@cabo.dk>
7
#
8

    
9
'''
10
Script and module for updating or combining a configuration file with
11
changes in a template.
12
'''
13

    
14
import itertools
15
import os
16
import sys
17

    
18
import configobj
19

    
20
def _readfile(path):
21
    ''' read the entire contents of 'path'. Equivalent to:
22

    
23
    >>> open(path).read()
24

    
25
    but without relying on reference counting to immediately close the file.
26
    '''
27
    with open(path) as fd:
28
        return fd.read()
29

    
30
def _removedups(lst):
31
    '''
32
    Return a copy of the list with all duplicates removed
33

    
34
    http://stackoverflow.com/a/6197827/136864
35
    '''
36
    dset = set()
37

    
38
    # relies on the fact that dset.add() always returns None.
39
    return [ l for l in lst if
40
             l not in dset and not dset.add(l) ]
41

    
42

    
43
def combineconfig(config, template):
44
    '''
45
    update the given config with new entries (and comments) from the
46
    template
47
    '''
48

    
49
    template = configobj.ConfigObj(template.splitlines())
50

    
51
    try:
52
        config = configobj.ConfigObj(config.splitlines(), raise_errors=True)
53
    except configobj.DuplicateError:
54
        config = \
55
            configobj.ConfigObj(_removedups(config.splitlines()))
56

    
57
    for key, value in config.items():
58
        if key not in template:
59
            template[key] = value
60
            template.comments[key] = config.comments[key] or ['']
61
            template.comments[key].append('# UNUSED!')
62
        else:
63
            template[key] = value
64

    
65
            if not template.comments[key] and any(config.comments[key]):
66
                template.comments[key] = config.comments[key]
67

    
68
    return template
69

    
70
def main(args):
71
    '''main entry point'''
72

    
73
    try:
74
        if len(args) != 3 and len(args) != 4:
75
            sys.stderr.write('usage: %s <config> <template> [dest]\n' %
76
                             os.path.basename(args[0]))
77
            return 1
78

    
79
        configpath = args[1]
80
        templatepath = args[2]
81

    
82
        config = combineconfig(_readfile(configpath), _readfile(templatepath))
83

    
84
        if len(args) == 4:
85
            with open(args[3], 'w') as outfd:
86
                config.write(outfd)
87
        else:
88
            config.write(sys.stdout)
89

    
90
        return 0
91
    except Exception as e:
92
        import traceback
93
        traceback.print_exc()
94
        return 1
95

    
96
if __name__ == '__main__':
97
    sys.exit(main(sys.argv))
(8-8/33)