Switch to unified view

a/rclconfig.py b/rclconfig.py
1
#!/usr/bin/env python
1
#!/usr/bin/env python3
2
from __future__ import print_function
2
3
3
import locale
4
import locale
4
import re
5
import re
5
import os
6
import os
6
import sys
7
import sys
7
import base64
8
import base64
9
import platform
8
10
9
class ConfSimple:
11
import conftree
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:
12
class RclDynConf:
128
    def __init__(self, fname):
13
    def __init__(self, fname):
129
        self.data = ConfSimple(fname)
14
        self.data = ConfSimple(fname)
130
15
131
    def getStringList(self, sk):
16
    def getStringList(self, sk):
...
...
136
                out.append(base64.b64decode(self.data.get(nm, sk)))
21
                out.append(base64.b64decode(self.data.get(nm, sk)))
137
        return out
22
        return out
138
    
23
    
139
class RclConfig:
24
class RclConfig:
140
    def __init__(self, argcnf = None):
25
    def __init__(self, argcnf = None):
26
        self.config = None
27
        platsys = platform.system()
141
        # Find configuration directory
28
        # Find configuration directory
142
        if argcnf is not None:
29
        if argcnf is not None:
143
            self.confdir = os.path.abspath(argcnf)
30
            self.confdir = os.path.abspath(argcnf)
144
        elif os.environ.has_key("RECOLL_CONFDIR"):
31
        elif "RECOLL_CONFDIR" in os.environ:
145
            self.confdir = os.environ["RECOLL_CONFDIR"]
32
            self.confdir = os.environ["RECOLL_CONFDIR"]
146
        else:
33
        else:
34
            if platsys == "Windows":
35
                if "LOCALAPPDATA" in os.environ:
36
                    dir = os.environ["LOCALAPPDATA"]
37
                else:
38
                    dir = os.path.expanduser("~")
39
                self.confdir = os.path.join(dir, "Recoll")
40
            else:
147
            self.confdir = os.path.expanduser("~/.recoll")
41
                self.confdir = os.path.expanduser("~/.recoll")
148
        #print "Confdir: [%s]" % self.confdir
42
        #print("Confdir: [%s]" % self.confdir, file=sys.stderr)
43
        
149
        # Also find datadir. This is trickier because this is set by
44
        # 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
45
        # "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
46
        # choose a preference order. Use RECOLL_DATADIR if the order is wrong
152
        self.datadir = None
47
        self.datadir = None
153
        if os.environ.has_key("RECOLL_DATADIR"):
48
        if "RECOLL_DATADIR" in os.environ:
154
            self.datadir = os.environ["RECOLL_DATADIR"]
49
            self.datadir = os.environ["RECOLL_DATADIR"]
155
        else:
50
        else:
51
            if platsys == "Windows":
52
                self.datadir = os.path.join(os.path.dirname(sys.argv[0]), "..")
53
            else:
156
            dirs = ("/opt/local", "/usr", "/usr/local")
54
                dirs = ("/opt/local", "/usr", "/usr/local")
157
            for dir in dirs:
55
                for dir in dirs:
158
                dd = os.path.join(dir, "share/recoll")
56
                    dd = os.path.join(dir, "share/recoll")
159
                if os.path.exists(dd):
57
                    if os.path.exists(dd):
160
                    self.datadir = dd
58
                        self.datadir = dd
161
        if self.datadir is None:
59
        if self.datadir is None:
162
            self.datadir = "/usr/share/recoll"
60
            self.datadir = "/usr/share/recoll"
163
        #print "Datadir: [%s]" % self.datadir
61
        #print("Datadir: [%s]" % self.datadir, file=sys.stderr)
62
        self.cdirs = []
63
        
64
        # Additional config directory, values override user ones
65
        if "RECOLL_CONFTOP" in os.environ:
66
            self.cdirs.append(os.environ["RECOLL_CONFTOP"])
164
        self.cdirs = [self.confdir,]
67
        self.cdirs.append(self.confdir)
68
        # Additional config directory, overrides system's, overridden by user's
69
        if "RECOLL_CONFMID" in os.environ:
70
            self.cdirs.append(os.environ["RECOLL_CONFMID"])
165
        self.cdirs.append(os.path.join(self.datadir, "examples"))
71
        self.cdirs.append(os.path.join(self.datadir, "examples"))
166
        #print self.cdirs
72
        #print("Config dirs: %s" % self.cdirs, file=sys.stderr)
167
        self.config = ConfStack("recoll.conf", self.cdirs, "tree")
168
        self.keydir = ''
73
        self.keydir = ''
169
74
170
    def getConfDir(self):
75
    def getConfDir(self):
171
        return self.confdir
76
        return self.confdir
172
    
77
    
173
    def setKeyDir(self, dir):
78
    def setKeyDir(self, dir):
174
        self.keydir = dir
79
        self.keydir = dir
175
80
176
    def getConfParam(self, nm):
81
    def getConfParam(self, nm):
82
        if not self.config:
83
            self.config = conftree.ConfStack("recoll.conf", self.cdirs, "tree")
177
        return self.config.get(nm, self.keydir)
84
        return self.config.get(nm, self.keydir)
178
        
85
        
179
class RclExtraDbs:
86
class RclExtraDbs:
180
    def __init__(self, config):
87
    def __init__(self, config):
181
        self.config = config
88
        self.config = config
...
...
183
    def getActDbs(self):
90
    def getActDbs(self):
184
        dyncfile = os.path.join(self.config.getConfDir(), "history")
91
        dyncfile = os.path.join(self.config.getConfDir(), "history")
185
        dync = RclDynConf(dyncfile)
92
        dync = RclDynConf(dyncfile)
186
        return dync.getStringList("actExtDbs")
93
        return dync.getStringList("actExtDbs")
187
    
94
    
95
if __name__ == '__main__':
96
    config = RclConfig()
97
    print(config.getConfParam("topdirs"))
98
    extradbs = RclExtraDbs(config)
99
    print(extradbs.getActDbs())