a/src/cdplugins/pycommon/conftree.py b/src/cdplugins/pycommon/conftree.py
1
/home/dockes/projets/docklib/python/conftree.py
1
#!/usr/bin/env python
2
from __future__ import print_function
3
4
import locale
5
import re
6
import os
7
import sys
8
import base64
9
import platform
10
11
class ConfSimple:
12
    """A ConfSimple class reads a recoll configuration file, which is a typical
13
    ini file (see the Recoll manual). It's a dictionary of dictionaries which
14
    lets you retrieve named values from the top level or a subsection"""
15
16
    def __init__(self, confname, tildexp = False):
17
        self.submaps = {}
18
        self.dotildexpand = tildexp
19
        try:
20
            f = open(confname, 'r')
21
        except Exception as exc:
22
            #print("Open Exception: %s" % exc, sys.stderr)
23
            # File does not exist -> empty config, not an error.
24
            return
25
26
        self.parseinput(f)
27
        
28
    def parseinput(self, f):
29
        appending = False
30
        line = ''
31
        submapkey = ''
32
        for cline in f:
33
            cline = cline.rstrip("\r\n")
34
            if appending:
35
                line = line + cline
36
            else:
37
                line = cline
38
            line = line.strip()
39
            if line == '' or line[0] == '#':
40
                continue
41
42
            if line[len(line)-1] == '\\':
43
                line = line[0:len(line)-1]
44
                appending = True
45
                continue
46
            appending = False
47
            #print(line)
48
            if line[0] == '[':
49
                line = line.strip('[]')
50
                if self.dotildexpand:
51
                    submapkey = os.path.expanduser(line)
52
                else:
53
                    submapkey = line
54
                #print("Submapkey: [%s]" % submapkey)
55
                continue
56
            nm, sep, value = line.partition('=')
57
            if sep == '':
58
                continue
59
            nm = nm.strip()
60
            value = value.strip()
61
            #print("Name: [%s] Value: [%s]" % (nm, value))
62
63
            if not submapkey in self.submaps:
64
                self.submaps[submapkey] = {}
65
            self.submaps[submapkey][nm] = value
66
67
    def get(self, nm, sk = ''):
68
        '''Returns None if not found, empty string if found empty'''
69
        if not sk in self.submaps:
70
            return None
71
        if not nm in self.submaps[sk]:
72
            return None
73
        return self.submaps[sk][nm]
74
75
    def getNames(self, sk = ''):
76
        if not sk in self.submaps:
77
            return None
78
        return list(self.submaps[sk].keys())
79
    
80
class ConfTree(ConfSimple):
81
    """A ConfTree adds path-hierarchical interpretation of the section keys,
82
    which should be '/'-separated values. When a value is requested for a
83
    given path, it will also be searched in the sections corresponding to
84
    the ancestors. E.g. get(name, '/a/b') will also look in sections '/a' and
85
    '/' or '' (the last 2 are equivalent)"""
86
    def get(self, nm, sk = ''):
87
        if sk == '' or sk[0] != '/':
88
            return ConfSimple.get(self, nm, sk)
89
            
90
        if sk[len(sk)-1] != '/':
91
            sk = sk + '/'
92
93
        # Try all sk ancestors as submaps (/a/b/c-> /a/b/c, /a/b, /a, '')
94
        while sk.find('/') != -1:
95
            val = ConfSimple.get(self, nm, sk)
96
            if val is not None:
97
                return val
98
            i = sk.rfind('/')
99
            if i == -1:
100
                break
101
            sk = sk[:i]
102
103
        return ConfSimple.get(self, nm)
104
105
class ConfStack:
106
    """ A ConfStack manages the superposition of a list of Configuration
107
    objects. Values are looked for in each object from the list until found.
108
    This typically provides for defaults overriden by sparse values in the
109
    topmost file."""
110
111
    def __init__(self, nm, dirs, tp = 'simple'):
112
        fnames = []
113
        for dir in dirs:
114
            fnm = os.path.join(dir, nm)
115
            fnames.append(fnm)
116
            self._construct(tp, fnames)
117
118
    def _construct(self, tp, fnames):
119
        self.confs = []
120
        for fname in fnames:
121
            if tp.lower() == 'simple':
122
                conf = ConfSimple(fname)
123
            else:
124
                conf = ConfTree(fname)
125
            self.confs.append(conf)
126
127
    def get(self, nm, sk = ''):
128
        for conf in self.confs:
129
            value = conf.get(nm, sk)
130
            if value is not None:
131
                return value
132
        return None
133
134
if __name__ == '__main__':
135
    def Usage():
136
        print("Usage: conftree.py <filename> <paramname> [<section>]",
137
              file=sys.stderr)
138
        sys.exit(1)
139
    section = ''
140
    if len(sys.argv) >= 3:
141
        fname = sys.argv[1]
142
        pname = sys.argv[2]
143
        if len(sys.argv) == 4:
144
            section = sys.argv[3]
145
        elif len(sys.argv) != 3:
146
            Usage()
147
    else:
148
        Usage()
149
150
    conf = ConfSimple(fname)
151
    if section:
152
        print("[%s] %s -> %s" % (section, pname, conf.get(pname)))
153
    else:
154
        print("%s -> %s" % (pname, conf.get(pname)))