Switch to unified view

a b/rclconfig.py
1
#!/usr/bin/env python
2
3
import locale
4
import re
5
import os
6
import sys
7
import base64
8
9
class ConfSimple:
10
    """A ConfSimple class reads a recoll configuration file, which is a typical
11
    ini file (see the Recoll manual). It's a dictionary of dictionaries which
12
    lets you retrieve named values from the top level or a subsection"""
13
14
    def __init__(self, confname, tildexp = False):
15
        f = open(confname, 'r')
16
        self.dotildexpand = tildexp
17
        self.submaps = {}
18
19
        self.parseinput(f)
20
        
21
    def parseinput(self, f):
22
        appending = False
23
        line = ''
24
        submapkey = ''
25
        for cline in f:
26
            cline = cline.rstrip("\r\n")
27
            if appending:
28
                line = line + cline
29
            else:
30
                line = cline
31
            line = line.strip()
32
            if line == '' or line[0] == '#':
33
                continue
34
35
            if line[len(line)-1] == '\\':
36
                line = line[0:len(line)-1]
37
                appending = True
38
                continue
39
            appending = False
40
            #print line
41
            if line[0] == '[':
42
                line = line.strip('[]')
43
                if self.dotildexpand:
44
                    submapkey = os.path.expanduser(line)
45
                else:
46
                    submapkey = line
47
                #print "Submapkey:", submapkey
48
                continue
49
            nm, sep, value = line.partition('=')
50
            if sep == '':
51
                continue
52
            nm = nm.strip()
53
            value = value.strip()
54
            #print "Name:", nm, "Value:", value
55
56
            if not self.submaps.has_key(submapkey):
57
                self.submaps[submapkey] = {}
58
            self.submaps[submapkey][nm] = value
59
60
    def get(self, nm, sk = ''):
61
        '''Returns None if not found, empty string if found empty'''
62
        if not self.submaps.has_key(sk):
63
            return None
64
        if not self.submaps[sk].has_key(nm):
65
            return None
66
        return self.submaps[sk][nm]
67
68
    def getNames(self, sk = ''):
69
        if not self.submaps.has_key(sk):
70
            return None
71
        return self.submaps[sk].keys()
72
    
73
class ConfTree(ConfSimple):
74
    """A ConfTree adds path-hierarchical interpretation of the section keys,
75
    which should be '/'-separated values. When a value is requested for a
76
    given path, it will also be searched in the sections corresponding to
77
    the ancestors. E.g. get(name, '/a/b') will also look in sections '/a' and
78
    '/' or '' (the last 2 are equivalent"""
79
    def get(self, nm, sk = ''):
80
        if sk == '' or sk[0] != '/':
81
            return ConfSimple.get(self, nm, sk)
82
            
83
        if sk[len(sk)-1] != '/':
84
            sk = sk + '/'
85
86
        # Try all sk ancestors as submaps (/a/b/c-> /a/b/c, /a/b, /a, '')
87
        while sk.find('/') != -1:
88
            val = ConfSimple.get(self, nm, sk)
89
            if val is not None:
90
                return val
91
            i = sk.rfind('/')
92
            if i == -1:
93
                break
94
            sk = sk[:i]
95
96
        return ConfSimple.get(self, nm)
97
98
class ConfStack:
99
    """ A ConfStack manages the superposition of a list of Configuration
100
    objects. Values are looked for in each object from the list until found.
101
    This typically provides for defaults overriden by sparse values in the
102
    topmost file."""
103
104
    def __init__(self, nm, dirs, tp = 'simple'):
105
        fnames = []
106
        for dir in dirs:
107
            fnm = os.path.join(dir, nm)
108
            fnames.append(fnm)
109
            self._construct(tp, fnames)
110
111
    def _construct(self, tp, fnames):
112
        self.confs = []
113
        for fname in fnames:
114
            if tp.lower() == 'simple':
115
                conf = ConfSimple(fname)
116
            else:
117
                conf = ConfTree(fname)
118
            self.confs.append(conf)
119
120
    def get(self, nm, sk = ''):
121
        for conf in self.confs:
122
            value = conf.get(nm, sk)
123
            if value is not None:
124
                return value
125
        return None
126
127
class RclDynConf:
128
    def __init__(self, fname):
129
        self.data = ConfSimple(fname)
130
131
    def getStringList(self, sk):
132
        nms = self.data.getNames(sk)
133
        out = []
134
        if nms is not None:
135
            for nm in nms:
136
                out.append(base64.b64decode(self.data.get(nm, sk)))
137
        return out
138
    
139
class RclConfig:
140
    def __init__(self, argcnf = None):
141
        # Find configuration directory
142
        if argcnf is not None:
143
            self.confdir = os.path.abspath(argcnf)
144
        elif os.environ.has_key("RECOLL_CONFDIR"):
145
            self.confdir = os.environ["RECOLL_CONFDIR"]
146
        else:
147
            self.confdir = os.path.expanduser("~/.recoll")
148
        #print "Confdir: [%s]" % self.confdir
149
        # Also find datadir. This is trickier because this is set by
150
        # "configure" in the C code. We can only do our best. Have to
151
        # choose a preference order. Use RECOLL_DATADIR if the order is wrong
152
        self.datadir = None
153
        if os.environ.has_key("RECOLL_DATADIR"):
154
            self.datadir = os.environ["RECOLL_DATADIR"]
155
        else:
156
            dirs = ("/opt/local", "/usr", "/usr/local")
157
            for dir in dirs:
158
                dd = os.path.join(dir, "share/recoll")
159
                if os.path.exists(dd):
160
                    self.datadir = dd
161
        if self.datadir is None:
162
            self.datadir = "/usr/share/recoll"
163
        #print "Datadir: [%s]" % self.datadir
164
        self.cdirs = [self.confdir,]
165
        self.cdirs.append(os.path.join(self.datadir, "examples"))
166
        #print self.cdirs
167
        self.config = ConfStack("recoll.conf", self.cdirs, "tree")
168
        self.keydir = ''
169
170
    def getConfDir(self):
171
        return self.confdir
172
    
173
    def setKeyDir(self, dir):
174
        self.keydir = dir
175
176
    def getConfParam(self, nm):
177
        return self.config.get(nm, self.keydir)
178
        
179
class RclExtraDbs:
180
    def __init__(self, config):
181
        self.config = config
182
183
    def getActDbs(self):
184
        dyncfile = os.path.join(self.config.getConfDir(), "history")
185
        dync = RclDynConf(dyncfile)
186
        return dync.getStringList("actExtDbs")
187