diff --git a/rclconfig.py b/rclconfig.py new file mode 100755 index 0000000..c6f5f01 --- /dev/null +++ b/rclconfig.py @@ -0,0 +1,187 @@ +#!/usr/bin/env python + +import locale +import re +import os +import sys +import base64 + +class ConfSimple: + """A ConfSimple class reads a recoll configuration file, which is a typical + ini file (see the Recoll manual). It's a dictionary of dictionaries which + lets you retrieve named values from the top level or a subsection""" + + def __init__(self, confname, tildexp = False): + f = open(confname, 'r') + self.dotildexpand = tildexp + self.submaps = {} + + self.parseinput(f) + + def parseinput(self, f): + appending = False + line = '' + submapkey = '' + for cline in f: + cline = cline.rstrip("\r\n") + if appending: + line = line + cline + else: + line = cline + line = line.strip() + if line == '' or line[0] == '#': + continue + + if line[len(line)-1] == '\\': + line = line[0:len(line)-1] + appending = True + continue + appending = False + #print line + if line[0] == '[': + line = line.strip('[]') + if self.dotildexpand: + submapkey = os.path.expanduser(line) + else: + submapkey = line + #print "Submapkey:", submapkey + continue + nm, sep, value = line.partition('=') + if sep == '': + continue + nm = nm.strip() + value = value.strip() + #print "Name:", nm, "Value:", value + + if not self.submaps.has_key(submapkey): + self.submaps[submapkey] = {} + self.submaps[submapkey][nm] = value + + def get(self, nm, sk = ''): + '''Returns None if not found, empty string if found empty''' + if not self.submaps.has_key(sk): + return None + if not self.submaps[sk].has_key(nm): + return None + return self.submaps[sk][nm] + + def getNames(self, sk = ''): + if not self.submaps.has_key(sk): + return None + return self.submaps[sk].keys() + +class ConfTree(ConfSimple): + """A ConfTree adds path-hierarchical interpretation of the section keys, + which should be '/'-separated values. When a value is requested for a + given path, it will also be searched in the sections corresponding to + the ancestors. E.g. get(name, '/a/b') will also look in sections '/a' and + '/' or '' (the last 2 are equivalent""" + def get(self, nm, sk = ''): + if sk == '' or sk[0] != '/': + return ConfSimple.get(self, nm, sk) + + if sk[len(sk)-1] != '/': + sk = sk + '/' + + # Try all sk ancestors as submaps (/a/b/c-> /a/b/c, /a/b, /a, '') + while sk.find('/') != -1: + val = ConfSimple.get(self, nm, sk) + if val is not None: + return val + i = sk.rfind('/') + if i == -1: + break + sk = sk[:i] + + return ConfSimple.get(self, nm) + +class ConfStack: + """ A ConfStack manages the superposition of a list of Configuration + objects. Values are looked for in each object from the list until found. + This typically provides for defaults overriden by sparse values in the + topmost file.""" + + def __init__(self, nm, dirs, tp = 'simple'): + fnames = [] + for dir in dirs: + fnm = os.path.join(dir, nm) + fnames.append(fnm) + self._construct(tp, fnames) + + def _construct(self, tp, fnames): + self.confs = [] + for fname in fnames: + if tp.lower() == 'simple': + conf = ConfSimple(fname) + else: + conf = ConfTree(fname) + self.confs.append(conf) + + def get(self, nm, sk = ''): + for conf in self.confs: + value = conf.get(nm, sk) + if value is not None: + return value + return None + +class RclDynConf: + def __init__(self, fname): + self.data = ConfSimple(fname) + + def getStringList(self, sk): + nms = self.data.getNames(sk) + out = [] + if nms is not None: + for nm in nms: + out.append(base64.b64decode(self.data.get(nm, sk))) + return out + +class RclConfig: + def __init__(self, argcnf = None): + # Find configuration directory + if argcnf is not None: + self.confdir = os.path.abspath(argcnf) + elif os.environ.has_key("RECOLL_CONFDIR"): + self.confdir = os.environ["RECOLL_CONFDIR"] + else: + self.confdir = os.path.expanduser("~/.recoll") + #print "Confdir: [%s]" % self.confdir + # Also find datadir. This is trickier because this is set by + # "configure" in the C code. We can only do our best. Have to + # choose a preference order. Use RECOLL_DATADIR if the order is wrong + self.datadir = None + if os.environ.has_key("RECOLL_DATADIR"): + self.datadir = os.environ["RECOLL_DATADIR"] + else: + dirs = ("/opt/local", "/usr", "/usr/local") + for dir in dirs: + dd = os.path.join(dir, "share/recoll") + if os.path.exists(dd): + self.datadir = dd + if self.datadir is None: + self.datadir = "/usr/share/recoll" + #print "Datadir: [%s]" % self.datadir + self.cdirs = [self.confdir,] + self.cdirs.append(os.path.join(self.datadir, "examples")) + #print self.cdirs + self.config = ConfStack("recoll.conf", self.cdirs, "tree") + self.keydir = '' + + def getConfDir(self): + return self.confdir + + def setKeyDir(self, dir): + self.keydir = dir + + def getConfParam(self, nm): + return self.config.get(nm, self.keydir) + +class RclExtraDbs: + def __init__(self, config): + self.config = config + + def getActDbs(self): + dyncfile = os.path.join(self.config.getConfDir(), "history") + dync = RclDynConf(dyncfile) + return dync.getStringList("actExtDbs") + diff --git a/webui.py b/webui.py index 9fc6d4b..85cee77 100755 --- a/webui.py +++ b/webui.py @@ -4,15 +4,6 @@ import os import bottle import time import sys - -try: - from recoll import recoll - from recoll import rclextract - hasrclextract = True -except: - import recoll - hasrclextract = False - import datetime import glob import hashlib @@ -23,12 +14,21 @@ import ConfigParser import string import shlex import urllib -from pprint import pprint +# import recoll and rclextract +try: + from recoll import recoll + from recoll import rclextract + hasrclextract = True +except: + import recoll + hasrclextract = False +# import rclconfig system-wide or local copy +try: + from recoll import rclconfig +except: + import rclconfig #}}} #{{{ settings -# recoll settings -RECOLL_CONFS = [ '$RECOLL_CONFDIR', '~/.recoll', '/usr/share/recoll/examples' ] - # settings defaults DEFAULTS = { 'context': 30, @@ -97,34 +97,13 @@ def normalise_filename(fn): out += "_" return out #}}} -#{{{ recoll_get_config -def recoll_get_config(): - # find recoll.conf - for d in RECOLL_CONFS: - d = os.path.expanduser(d) - d = os.path.expandvars(d) - if os.path.isdir(d): - confdir = d - break - # read recoll.conf - rc_ini_str = '[main]\n' + open(confdir + '/recoll.conf', 'r').read().replace('\\\n', '') - rc_ini_fp = StringIO.StringIO(rc_ini_str) - rc_ini = ConfigParser.RawConfigParser() - rc_ini.readfp(rc_ini_fp) - # parse recoll.conf - rc = {} - for s in rc_ini.sections(): - rc[s] = {} - for k, v in rc_ini.items(s): - rc[s][k] = v - return confdir, rc -#}}} #{{{ get_config def get_config(): config = {} # get useful things from recoll.conf - config['confdir'], rc = recoll_get_config() - config['dirs'] = shlex.split(rc['main']['topdirs']) + rclconf = rclconfig.RclConfig() + config['confdir'] = rclconf.getConfDir() + config['dirs'] = shlex.split(rclconf.getConfParam('topdirs')) # get config from cookies or defaults for k, v in DEFAULTS.items(): value = select([bottle.request.get_cookie(k), v])