def set(target, txtlist): """ set target entry to list. """ cache = Persist(getdatadir() + os.sep + 'run' + os.sep + 'outputcache' + os.sep + stripname(target)) if not cache.data.has_key('msg'): cache.data['msg'] = [] cache.data['msg'] = txtlist cache.save()
def clear(target): """ clear target's outputcache. """ cache = Persist(getdatadir() + os.sep + 'run' + os.sep + 'outputcache' + os.sep + stripname(target)) try: cache.data['msg'] = [] cache.save() except KeyError: pass return []
def save(self): """ save fleet data and call save on all the bots. """ Persist.save(self) for i in self.bots: try: i.save() except Exception, ex: handle_exception()
def add(target, txtlist): """ add list of txt to target entry. """ logging.warn("outputcache - adding %s lines" % len(txtlist)) t = [] for item in txtlist: t.append("[%s] %s" % (hourmin(time.time()), item)) cache = Persist(getdatadir() + os.sep + 'run' + os.sep + 'outputcache' + os.sep + stripname(target)) d = cache.data if not d.has_key('msg'): d['msg'] = [] d['msg'].extend(t) while len(d['msg']) > 10: d['msg'].pop(0) cache.save()
class Stats(): def __init__(self): self.nr_moves = 0 self.nr_search_steps = 0 self.current_nr_search_moves = 0 self.persist = Persist() def reset(self): self.nr_moves = 0 self.nr_search_steps = 0 self.current_nr_search_moves = 0 def save(self, data): chunk = { 'state' : data, 'nr_moves' : self.nr_moves, 'nr_search_steps' : self.nr_search_steps } self.persist.save(chunk)
class Taskhat: HELP_STRING = ' Enter a new task:' def __init__(self): if DBUS_OK: self.dbus_presence = TaskhatDBusPresence(self) self.persist = Persist('Default') self.window = gtk.Window() self.window.connect('delete_event', self.close) self.window.set_title('Taskhat') self.window.set_icon_name('gtg-panel') self.window.realize() box1 = gtk.VBox() box2 = gtk.HBox() box2.set_border_width(4) abox = gtk.HBox() image = gtk.Image() image.set_from_stock(gtk.STOCK_ADD, gtk.ICON_SIZE_MENU) label = gtk.Label('Add') abox.pack_start(image, False, False, 0) abox.pack_start(label, False, False, 0) abox.show() image.show() label.show() abutton = self.abutton = gtk.ToolButton(abox, 'Add') abutton.set_sensitive(False) abutton.connect('clicked', self.entry_done) abutton.show() abox = gtk.HBox() image = gtk.Arrow(gtk.ARROW_DOWN, gtk.SHADOW_IN) abox.pack_start(image, False, False, 0) abox.show() image.show() tool = gtk.ToolButton(abox, 'Tools') def documentation(*args): dialog = gtk.MessageDialog(parent=self.window, flags=gtk.DIALOG_MODAL) dialog.set_title('User Information') dialog.set_markup('A priority of <b>%s</b> denotes administrivia.\nA priority of <b>%s</b> denotes an important task.\nA priority of <b>%s</b> is for normal tasks.\nA priority of <b>%s</b> denotes a low priority task.\n\nOver time, Taskhat will learn how you like to classify your tasks.\n\nSee <b>taskhat/config.py</b> for more options.' % (Task.PRIORITY_ADMIN.name, Task.PRIORITY_HIGH.name, Task.PRIORITY_MEDIUM.name, Task.PRIORITY_LOW.name)) button = gtk.Button(stock=gtk.STOCK_CLOSE) def dest(*args): dialog.destroy() button.connect('clicked', dest) button.show() dialog.action_area.pack_end(button) dialog.show() popup_menu = gtk.Menu() s = 'Edit Recurring Events' x = gtk.MenuItem(s) x.connect('activate', self.event_editor) x.show() popup_menu.append(x) s = 'Revert Changes' x = gtk.MenuItem(s) x.connect('activate', self.backup_restore) x.show() popup_menu.append(x) x = gtk.SeparatorMenuItem() x.show() popup_menu.append(x) s = 'Information' x = gtk.MenuItem(s) x.connect('activate', documentation) x.show() popup_menu.append(x) s = 'About' x = gtk.MenuItem(s) x.connect('activate', self.about_menu) x.show() popup_menu.append(x) popup_menu.attach_to_widget(tool, None) popup_menu.show() def tool_menu(widget): popup_menu.popup(None, None, None, 1, 0) tool.connect('clicked', tool_menu) entry = self.entry = gtk.Entry() entry.connect('changed', self.entry_changed) entry.connect('activate', self.entry_done) entry.set_width_chars(25) entry.show() scrolled_window = gtk.ScrolledWindow() scrolled_window.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC) scrolled_window.show() box3 = gtk.VBox() box3.show() ebox3 = self.ebox3 = gtk.EventBox() ebox3.add(box3) ebox3.show() scrolled_window.add_with_viewport(ebox3) # TaskGroup('Overdue', self.window, self.persist, (-TaskDate.FUTURE+1, -1)) TaskGroup('Today', self.window, self.persist, (None, 0), events=CONFIG['show_recurring_events']) TaskGroup('Tomorrow', self.window, self.persist, (1, 1)) # TaskGroup('Today & Tomorrow', self.window, self.persist, (None, 1), events=CONFIG['show_recurring_events']) TaskGroup('Next few days', self.window, self.persist, (2, 5)) TaskGroup('Next week', self.window, self.persist, (6, 14)) TaskGroup('Future', self.window, self.persist, (8, None)) for group in TaskGroup.groups: box3.pack_start(group, False, False) ebox3.modify_bg(gtk.STATE_NORMAL, self.window.get_style().base[gtk.STATE_NORMAL]) status = self.status = gtk.Label(Taskhat.HELP_STRING) status.set_alignment(0,.5) status.set_ellipsize(pango.ELLIPSIZE_END) status.show() status.set_sensitive(False) box2.pack_start(status, True, True) sep = gtk.Label(' ') sep.show() box2.pack_start(sep, False, False) sep = gtk.VSeparator() sep.show() box2.pack_end(tool, False, False) box2.pack_end(sep, False, False) box2.pack_end(abutton, False, False) tool.show() box2.pack_end(entry, False, False) box1.pack_start(box2, False, False) box1.pack_start(scrolled_window) self.window.add(box1) self.window.set_size_request(530, 565) box2.show() box1.show() accelgroup = gtk.AccelGroup() self.window.add_accel_group(accelgroup) action = gtk.Action('Quit', '_Quit me!', 'Quit the Program', gtk.STOCK_QUIT) action.connect('activate', self.close) actiongroup = gtk.ActionGroup('BasicAction') actiongroup.add_action_with_accel(action, None) action.set_accel_group(accelgroup) menubar = gtk.MenuBar() menuitem = action.create_menu_item() menubar.append(menuitem) box1.pack_start(menubar, False) TaskGroup.origin = scrolled_window self.persist.restore(self.insert_task, self.update_events) self.persist.restore_geometry(self.window) persist.load_classifiers() self.window.show() entry.grab_focus() self.window.connect('notify::style', self.update_group_styles) self.window.connect('notify::is-active', self.save_geom) def _callback(data): self.clear_all() new = filter(lambda t: not t.removed, data.get('tasks', [])) taskhat_write = data.get('last_taskhat_update', now()) taskhat_write += datetime.timedelta(seconds=1) closed = set() for task in new: closed.add(repr(task)) for task in self.persist.tasks: if task.last_updated > taskhat_write and repr(task) not in closed: new.append(task) self.persist.tasks = new for task in new: self.insert_task(task) task.last_updated = taskhat_write self.persist.events =\ filter(lambda e: not e.deleted, data.get('events', [])) self.persist.sync() self.update_events() return False def callback_gobject_wrapper(data): gobject.idle_add(lambda: _callback(data)) file_api.watch(callback_gobject_wrapper) def save_geom(self, *args): self.persist.save_geometry(self.window.get_position(), self.window.get_size()) def clear_all(self): for g in TaskGroup.groups: g.clear() def update_events(self): for g in TaskGroup.groups: g.update(True) def event_editor(self, *args): EventEditor(self.window, self.persist, self).run() def backup_restore(self, *args): RestoreFromBackup(self.window, self.persist, self).run() def update_group_styles(self, args, x): self.ebox3.modify_bg(gtk.STATE_NORMAL, self.window.get_style().base[gtk.STATE_NORMAL]) def get_active_text(self, combobox): model = combobox.get_model() active = combobox.get_active() if active < 0: return None return model[active][0] def entry_changed(self, widget, data=None): text = self.entry.get_text().strip() if text: self.abutton.set_sensitive(True) self.status.set_label(label_from_string(text)[0]) else: self.abutton.set_sensitive(False) self.status.set_label(Taskhat.HELP_STRING) def insert_task(self, task): TaskGroup.groups[0].smart_assign(task) def entry_done(self, widget, data=None): text = self.entry.get_text().strip() if text: task = task_from_string(self.entry.get_text()) self.insert_task(task) self.persist.save(task) self.entry.set_text('') def close(self, widget, data=None): if CONFIG['run_in_background']: map(TaskGroup.remove_removed, TaskGroup.groups) self.entry.set_text('') self.window.hide() return True else: gtk.main_quit() def about_menu(self, *args): dialog = gtk.AboutDialog() dialog.set_name('Taskhat') dialog.set_version('0.2') dialog.set_comments('Taskhat lets you manage tasks and events, over both the short and long term.') dialog.set_copyright('Copyright \xc2\xa9 2010 Eric Liang') dialog.run() dialog.hide() def main(self): try: from ctypes import cdll cdll.LoadLibrary('libc.so.6').prctl(15, 'taskhat', 0, 0, 0) except: pass def handler(e_type, e_value, e_trace): sys.excepthook = sys.__excepthook__ msg = str(e_value) + '\n' msg += '\n'.join(traceback.format_tb(e_trace)) msg += '\n' + 'Further exceptions will not be shown.' dialog = gtk.MessageDialog(parent=self.window, buttons=gtk.BUTTONS_OK, flags=gtk.DIALOG_MODAL, type=gtk.MESSAGE_ERROR) dialog.set_title(str(e_type)) dialog.set_markup(escape(msg)) dialog.run() dialog.hide() sys.excepthook = handler gtk.main()
class Config(LazyDict): """ config class is a dict containing json strings. is writable to file and human editable. """ def __init__(self, filename=None, verbose=False, input={}, ddir=None, *args, **kw): LazyDict.__init__(self, input, *args, **kw) filename = filename or 'mainconfig' datadir = ddir or getdatadir() dir = datadir + os.sep + 'config' if datadir not in filename: cfile = dir + os.sep + filename else: cfile = filename logging.debug("config - filename is %s" % cfile) self.jsondb = None try: import waveapi ; self.isdb = True except ImportError: self.isdb = False if not self.comments: self.comments = {} try: try: self.fromfile(cfile) except IOError: logging.warn("can't read config from %s" % self.cfile) import waveapi from persist import Persist self.jsondb = Persist(cfile) self.update(self.jsondb.data) self.isdb = True logging.debug("config - fromdb - %s - %s" % (self.cfile, str(self))) except ImportError: handle_exception() self.isdb = False self.cfile = cfile self.dir = dir self.filename = filename self.init() if not self.owner: self.owner = [] if not self.uuid: self.uuid = str(uuid.uuid4()) def __deepcopy__(self, a): """ accessor function. """ return Config(input=self) def __getitem__(self, item): """ accessor function. """ if not self.has_key(item): return None else: return dict.__getitem__(self, item) def set(self, item, value): """ set item to value. """ dict.__setitem__(self, item, value) def fromdb(self): """ read config from database. """ from jsb.lib.persist import Persist logging.info("config - fromdb - %s" % self.cfile) tmp = Persist(self.cfile) self.update(tmp.data) def todb(self): """ save config to database. """ cp = dict(self) del cp['jsondb'] if not self.jsondb: from jsb.lib.persist import Persist self.jsondb = Persist(self.cfile) self.jsondb.data = cp self.jsondb.save() @savelocked def fromfile(self, filename): """ read config object from filename. """ curline = "" fname = filename logging.debug("config - fromfile - %s" % fname) if not os.path.exists(fname): return False comment = "" for line in open(fname, 'r'): curline = line curline = curline.strip() if curline == "": continue if curline.startswith('#'): comment = curline; continue if True: try: key, value = curline.split('=', 1) kkey = key.strip() self[kkey] = json.loads(unicode(value.strip())) if comment: self.comments[kkey] = comment comment = "" except ValueError: logging.warn("config - skipping line - unable to parse: %s" % line) self.cfile = fname return @savelocked def tofile(self, filename=None): """ save config object to file. """ if not filename: filename = self.cfile try: from os import mkdir except ImportError: logging.debug("can't save %s to file .. os.mkdir() not suported" % filename) return logging.debug("config - saving %s" % filename) if filename.startswith(os.sep): d = [os.sep,] else: d = [] for p in filename.split(os.sep)[:-1]: if not p: continue d.append(p) ddir = os.sep.join(d) if not os.path.isdir(ddir): logging.debug("persist - creating %s dir" % ddir) try: os.mkdir(ddir) except OSError, ex: logging.warn("persist - not saving - failed to make %s - %s" % (ddir, str(ex))) return written = [] curitem = None try: configtmp = open(filename + '.tmp', 'w') teller = 0 keywords = self.keys() keywords.sort() for keyword in keywords: value = self[keyword] if keyword in written: continue if keyword == 'name': continue if keyword == 'createdfrom': continue if keyword == 'cfile': continue if keyword == 'filename': continue if keyword == 'dir': continue if keyword == 'jsondb': continue if keyword == 'isdb': continue if keyword == 'optionslist': continue if keyword == 'gatekeeper': continue if keyword == "comments": continue if self.comments and self.comments.has_key(keyword): configtmp.write(self.comments[keyword] + u"\n") curitem = keyword try: configtmp.write('%s = %s\n' % (keyword, json.dumps(value))) except TypeError: logging.error("config - %s - can't serialize %s" % (filename, keyword)) ; continue teller += 1 configtmp.write("\n") configtmp.close() os.rename(filename + '.tmp', filename) return teller except Exception, ex: handle_exception() print "ERROR WRITING %s CONFIG FILE: %s .. %s" % (self.cfile, str(ex), curitem)
class Config(LazyDict): """ config class is a dict containing json strings. is writable to file and human editable. """ def __init__(self, filename, verbose=False, input={}, ddir=None, nolog=False, *args, **kw): assert filename LazyDict.__init__(self, input, *args, **kw) self.origname = filename self.origdir = ddir or getdatadir() self.setcfile(ddir, filename) self.jsondb = None if not self._comments: self._comments = {} try: import waveapi self.isdb = True self.isgae = True except ImportError: self.isgae = False self.isdb = False dodb = False try: logging.info("fromfile - %s from %s" % (self.origname, whichmodule(2))) self.fromfile(self.cfile) except IOError, ex: handle_exception() ; dodb = True if dodb or (self.isgae and not "mainconfig" in filename): try: from persist import Persist self.jsondb = Persist(self.cfile) if self.jsondb: self.merge(self.jsondb.data) logging.warn("fromdb - %s" % self.cfile) except ImportError: logging.warn("can't read config from %s - %s" % (self.cfile, str(ex))) self.init() if self.owner: logging.info("owner is %s" % self.owner) if not self.has_key("uuid"): self.setuuid() if not self.has_key("cfile"): self.cfile = self.setcfile(self.origdir, self.origname) assert self.cfile def setcfile(self, ddir, filename): self.filename = filename or 'mainconfig' self.datadir = ddir or getdatadir() self.dir = self.datadir + os.sep + 'config' self.cfile = self.dir + os.sep + filename def setuuid(self, save=True): logging.debug("setting uuid") self.uuid = str(uuid.uuid4()) if save: self.save() def __deepcopy__(self, a): """ accessor function. """ cfg = Config(self.filename, input=self, nolog=True) return cfg def __getitem__(self, item): """ accessor function. """ if not self.has_key(item): return None else: return LazyDict.__getitem__(self, item) def merge(self, cfg): """ merge in another cfg. """ self.update(cfg) def set(self, item, value): """ set item to value. """ LazyDict.__setitem__(self, item, value) def fromdb(self): """ read config from database. """ from jsb.lib.persist import Persist tmp = Persist(self.cfile) logging.debug("fromdb - %s - %s" % (self.cfile, tmp.data.tojson())) self.update(tmp.data) def todb(self): """ save config to database. """ cp = dict(self) del cp['jsondb'] if not self.jsondb: from jsb.lib.persist import Persist self.jsondb = Persist(self.cfile) self.jsondb.data = cp self.jsondb.save() def fromfile(self, filename=None): """ read config object from filename. """ curline = "" fname = filename or self.cfile if not fname: raise Exception(" %s - %s" % (self.cfile, self.dump())) if not os.path.exists(fname): logging.warn("config file %s doesn't exist yet" % fname) ; return False comment = "" for line in open(fname, 'r'): curline = line curline = curline.strip() if curline == "": continue if curline.startswith('#'): comment = curline; continue if True: try: key, value = curline.split('=', 1) kkey = key.strip() self[kkey] = json.loads(unicode(value.strip())) if comment: self._comments[kkey] = comment comment = "" except ValueError: logging.error("skipping line - unable to parse: %s" % line) #self.cfile = fname return def tofile(self, filename=None, stdout=False): """ save config object to file. """ if not filename: filename = self.cfile if not filename: raise Exception("no cfile found - %s" % whichmodule(3)) if self.isgae: logging.warn("can't save config file %s on GAE" % filename) ; return logging.warn("saving %s" % filename) if filename.startswith(os.sep): d = [os.sep,] else: d = [] for p in filename.split(os.sep)[:-1]: if not p: continue d.append(p) ddir = os.sep.join(d) if not os.path.isdir(ddir): logging.debug("persist - creating %s dir" % ddir) try: os.mkdir(ddir) except OSError, ex: logging.error("persist - not saving - failed to make %s - %s" % (ddir, str(ex))) return written = [] curitem = None later = [] try: if stdout: configtmp = sys.stdout else: configtmp = open(filename + '.tmp', 'w') configtmp.write('# ===========================================================\n#\n') configtmp.write("# JSONBOT CONFIGURATION FILE - %s\n" % filename) configtmp.write("#\n") configtmp.write('# last changed on %s\n#\n' % time.ctime(time.time())) configtmp.write("# This file contains configration data for the JSONBOT.\n") configtmp.write('# Variables are defined by "name = json value" pairs.\n') configtmp.write('# Make sure to use " in strings.\n#\n') configtmp.write('# The bot can edit this file!.\n#\n') configtmp.write('# ===========================================================\n\n') teller = 0 keywords = self.keys() keywords.sort() for keyword in keywords: value = self[keyword] if keyword in written: continue if keyword in ['isgae', 'origdir', 'origname', 'issaved', 'blacklist', 'whitelist', 'followlist', 'uuid', 'whitelist', 'datadir', 'name', 'createdfrom', 'cfile', 'filename', 'dir', 'isdb']: later.append(keyword) ; continue if keyword == 'jsondb': continue if keyword == 'optionslist': continue if keyword == 'gatekeeper': continue if keyword == "_comments": continue if self._comments and self._comments.has_key(keyword): configtmp.write(self._comments[keyword] + u"\n") curitem = keyword try: configtmp.write('%s = %s\n' % (keyword, json.dumps(value))) except TypeError: logging.error("%s - can't serialize %s" % (filename, keyword)) ; continue teller += 1 #configtmp.write("\n") configtmp.write('\n\n# ============================================================\n#\n') configtmp.write("# bot generated stuff.\n#\n") configtmp.write('# ============================================================\n\n') for keyword in later: if self._comments and self._comments.has_key(keyword): configtmp.write(self._comments[keyword] + u"\n") curitem = keyword value = self[keyword] try: configtmp.write(keyword + " = " + json.dumps(value) + "\n") except TypeError: logging.error("%s - can't serialize %s" % (filename, keyword)) ; continue teller += 1 #configtmp.write("\n") if not "mainconfig" in filename and self._comments: try: configtmp.write('\n\n# ============================================================\n#\n') configtmp.write("# possible other config variables.\n#\n") configtmp.write('# ============================================================\n\n') items = self._comments.keys() keys = self.keys() do = [] for var in items: if var not in keys: do.append(var) do.sort() for var in do: configtmp.write(u"# %s -=- %s\n" % (var, self._comments[var])) configtmp.write("\n\n") except Exception, ex: handle_exception() else: configtmp.write("\n\n# jsonbot can run multiple bots at once. see %s/config/fleet for their configurations.\n\n" % self.origdir) if not stdout: configtmp.close() os.rename(filename + '.tmp', filename) return teller except Exception, ex: handle_exception() logging.error("ERROR WRITING %s CONFIG FILE: %s .. %s" % (self.cfile, str(ex), curitem))
def save(self): Persist.save(self)