#!/usr/bin/env python import shlex def tokens(lexer): while 1: tok = lexer.get_token() if not tok: break yield tok def token_line(lexer): tok = eat(lexer) # print "Lexer token: %s" % tok l = [tok] ln = lexer.lineno while lexer.lineno == ln: tok = eat(lexer) l.append(tok) # print "Read: %s, token: %s" % (l, tok) return l class ConfigException(Exception): pass class Section(object): pass def eat(lexer): return lexer.get_token() def spit(token, lexer): lexer.push_token(token) class BackupConfig(object): default_sections = ['options', 'prerun', 'postrun', 'backup', 'databases'] list_sections = ['backup', 'databases', 'prerun', 'postrun'] defaults = { 'options' : { 'transport' : 'ssh', 'user' : 'backup', 'uri' : '155.246.68.100', }, 'prerun' : [], 'postrun' : [], 'filesystem' : ['/home/', '/etc/apache2/'], 'databases' : [['pg', 'all'], ['sqlite', '/var/trac/*/db/*.db']], } def __init__(self, file_or_filename): self.sections = [] self.section_dict = {} if isinstance(file_or_filename, file): self.read(file_or_filename) else: self.read(open(file_or_filename)) self.verify() def read(self, f): self.lexer = shlex.shlex(f, posix=True) self.lexer.wordchars += "./*?-" self.lexer.commenters += ';' ss = [] s = {} current_section = '' def do_section(section, token, lexer): if section in self.list_sections: l = [] while token != '[' and token: spit(token, lexer) l.append(token_line(lexer)) token = eat(lexer) spit(token, lexer) return l else: d = {} while token != '[' and token: if eat(lexer) != '=': raise ConfigException("Non-list sections must be 'name = name' pairs") d[token] = eat(lexer) token = eat(lexer) # we've reached either EOF or '[' # we want to spit the '[' back on spit(token, lexer) return d for token in tokens(self.lexer): if token == '[': section_name = '' tok = eat(self.lexer) while tok != ']': section_name += tok tok = eat(self.lexer) ss.append(section_name) current_section = section_name s[current_section] = '' else: s[current_section] = do_section(current_section, token, self.lexer) self.sections = ss self.section_dict = s def verify(self): """ for sec in self.opt_sections: if not self.has_section(sec): self.setupSectionDefaults(sec) """ def get_section(self, section): if section in self.list_sections: return self.section_dict[section] else: o = Section() for key,val in self.section_dict[section].items(): setattr(o, key, val) o.keys = self.section_dict[section].keys return o def has_section(self, section): return section in self.sections def setupSectionDefaults(self, section): """ self.add_section(section) d = self.opt_defaults[section] if isinstance(d, dict): for key,val in d: self.set(section, key, value) elif isinstance(d, list): for """ def destination(self): """Create a destination string. The rsync string will be: rsync (options) (source) (destination) Where (destination) will be a remote computer.""" section = self.get_section('options') ds = '' if hasattr(section, 'user'): ds += '%s@' % (section.user) ds += section.uri if section.uri.endswith('/'): ds = ds[:-1] if hasattr(section, 'dest'): ds += ':' + section.dest return ds def arguments(self): section = self.get_section('options') argstr = '' if hasattr(section, 'rsync_opts'): argstr += '%s ' % section.rsync_opts if hasattr(section, 'transport'): argstr += '-e "%s" ' % section.transport return argstr def rsync(self): """Convenience function.""" return 'rsync ' + self.arguments() def main(): cfg = BackupConfig('backup.cfg') for section,contents in cfg.section_dict.items(): print "[%s] :" % section print contents if __name__ == '__main__': main()