#!/usr/local/bin/python # Reminder # # Douglas Thrift # # $Id$ from ConfigParser import NoOptionError, SafeConfigParser import gdata.calendar.service import getpass import imaplib import keyring import optparse import os import sys MODULES = frozenset(('creditcards', 'facebook')) class Config(object): def __init__(self, config, module): self.config = config self.module = module def get(self, *args, **kwargs): return self.config.get(self.module, *args, **kwargs) def getboolean(self, *args, **kwargs): return self.config.getboolean(self.module, *args, **kwargs) def getfloat(self, *args, **kwargs): return self.config.getfloat(self.module, *args, **kwargs) def getint(self, *args, **kwargs): return self.config.getint(self.module, *args, **kwargs) def getlist(self, *args, **kwargs): return self.config.getlist(self.module, *args, **kwargs) def getpassword(self): return self.config.getpassword(self.module) def getusername(self): return self.config.getusername(self.module) class ConfigParser(SafeConfigParser): def __init__(self, *args, **kwargs): SafeConfigParser.__init__(self, *args, **kwargs) def getlist(self, *args, **kwargs): return self.get(*args, **kwargs).split(',') def getpassword(self, section): return keyring.get_password('reminder_%s' % section, self.getusername(section)) def getusername(self, section): return self.get(section, 'username') class OptionParser(optparse.OptionParser): def __init__(self, *args, **kwargs): optparse.OptionParser.__init__(self, *args, **kwargs) self.add_option('-A', '--all', action = 'store_true', dest = 'all') self.add_option('-d', '--dbus', action = 'store_true', dest = 'dbus') self.add_option('-m', '--module', action = 'callback', callback = self.__module, dest = 'modules', type = 'string') self.add_option('-p', '--password', action = 'callback', callback = self.__password, dest = 'passwords', type = 'string') self.add_option('-D', '--debug', action = 'store_true', dest = 'debug') def __module(self, option, opt_str, value, parser): if value not in MODULES: raise optparse.OptionValueError, '%s unknown module %s' % (opt_str, value) parser.values.ensure_value(option.dest, []).append(value) def __password(self, option, opt_str, value, parser): parser.values.ensure_value(option.dest, []).append(value) class OnDemand(object): def __init__(self, constructor, destructor = None): self.constructor = constructor self.destructor = destructor self.instance = None def __getattr__(self, name): if self.instance is None: self.instance = self.constructor() return getattr(self.instance, name) def __del__(self): if self.destructor is not None and self.instance is not None: self.destructor(self.instance) if __name__ == '__main__': parser = OptionParser() options = parser.parse_args()[0] config = ConfigParser() config.read([os.path.expanduser('~/.reminder')]) if options.dbus: dbus = os.environ['DBUS_SESSION_BUS_ADDRESS'] with open(os.path.expanduser('~/.reminder.dbus'), 'wb') as file: file.write(dbus + '\n') sys.exit(0) try: os.environ['DBUS_SESSION_BUS_ADDRESS'] except KeyError: with open(os.path.expanduser('~/.reminder.dbus'), 'rb') as file: os.environ['DBUS_SESSION_BUS_ADDRESS'] = file.readline().rstrip() if options.passwords: for section in options.passwords: try: username = config.getusername(section) password = getpass.getpass('%s password for %s: ' % (section, username)) keyring.set_password('reminder_%s' % section, username, password) except NoOptionError: pass sys.exit(0) if not options.all and not options.modules: parser.error('-A or -m not specified') def calendar_constructor(): calendar = gdata.calendar.service.CalendarService() calendar.email = config.getusername('google') calendar.password = config.getpassword('google') calendar.source = 'Reminder-0.9' calendar.ProgrammaticLogin() return calendar def imap_constructor(): if options.debug: imaplib.Debug = 4 imap = imaplib.IMAP4_SSL(config.get('imap', 'server')) imap.login(config.getusername('imap'), config.getpassword('imap')) return imap calendar = OnDemand(calendar_constructor) imap = OnDemand(imap_constructor, lambda imap: imap.logout()) for module in options.modules if not options.all else sorted(MODULES): exec 'import %s' % module exec '%s.main(calendar, imap, Config(config, module), options.debug)' % module