From daaffb78e78bff2bdd739ff401b2b8217c2407c1 Mon Sep 17 00:00:00 2001 From: Thomas Vander Stichele Date: Sun, 3 May 2009 17:04:42 +0000 Subject: [PATCH] * morituri/common/common.py: Create a Persister class to wrap a possible pickle path. * examples/trm.py: Use it. --- ChangeLog | 7 ++++ examples/trm.py | 33 ++++++------------ morituri/common/common.py | 72 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 89 insertions(+), 23 deletions(-) diff --git a/ChangeLog b/ChangeLog index daa3cd4..76f7528 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2009-05-03 Thomas Vander Stichele + + * morituri/common/common.py: + Create a Persister class to wrap a possible pickle path. + * examples/trm.py: + Use it. + 2009-05-03 Thomas Vander Stichele * morituri/program/cdparanoia.py: diff --git a/examples/trm.py b/examples/trm.py index eb34e5b..1e89865 100644 --- a/examples/trm.py +++ b/examples/trm.py @@ -31,7 +31,7 @@ import gobject gobject.threads_init() import gtk -from morituri.common import checksum, task, taskgtk +from morituri.common import checksum, task, taskgtk, common def gtkmain(runner, taskk): runner.connect('stop', lambda _: gtk.main_quit()) @@ -48,9 +48,8 @@ def climain(runner, taskk): runner.run(taskk) class Listener(object): - def __init__(self, path): - self.path = path - self.trms = {} + def __init__(self, persister): + self._persister = persister def progressed(self, task, value): pass @@ -62,14 +61,9 @@ class Listener(object): pass def stopped(self, task): - self.trms[task.path] = task.trm + self._persister.object[task.path] = task.trm print task.path, task.trm - - (fd, path) = tempfile.mkstemp(suffix='.morituri') - handle = os.fdopen(fd, 'wb') - pickle.dump(self.trms, handle, 2) - handle.close() - shutil.move(path, self.path) + self._persister.persist() def main(argv): @@ -98,19 +92,12 @@ def main(argv): mtask = task.MultiCombinedTask() listener = None - trms = {} - if options.pickle: - listener = Listener(options.pickle) - print 'Opening pickle %s' % options.pickle - handle = open(options.pickle) - try: - trms = pickle.load(handle) - except Exception, e: - sys.stderr.write( - "Pickle file '%s' cannot be loaded.\n" % options.pickle) - sys.exit(1) - handle.close() + ptrms = common.Persister(options.pickle or None, {}) + if options.pickle: + listener = Listener(ptrms) + print 'Using pickle %s' % options.pickle + trms = ptrms.object for path in paths: path = path.rstrip() diff --git a/morituri/common/common.py b/morituri/common/common.py index 6c6cdcb..32fc23d 100644 --- a/morituri/common/common.py +++ b/morituri/common/common.py @@ -20,6 +20,10 @@ # You should have received a copy of the GNU General Public License # along with morituri. If not, see . +import os +import tempfile +import shutil + def msfToFrames(msf): """ Converts a string value in MM:SS:FF to frames @@ -57,3 +61,71 @@ def framesToHMSF(frames): h = frames / 75 / 60 / 60 return "%02d:%02d:%02d.%02d" % (h, m, s, f) + +class Persister(object): + """ + I wrap an optional pickle to persist an object to disk. + + Instantiate me with a path to automatically unpickle the object. + Call persist to store the object to disk; it will get stored if it + changed from the on-disk object. + + @ivar object: the persistent object + """ + + def __init__(self, path=None, default=None): + """ + If path is not given, the object will not be persisted. + This allows code to transparently deal with both persisted and + non-persisted objects, since the persist method will just end up + doing nothing. + """ + self._path = path + self.object = None + + self._unpickle(default) + + def persist(self, object=None): + """ + Persist the given object, if we have a persistence path and the + object changed. + + If object is not given, re-persist our object, always. + If object is given, only persist if it was changed. + """ + # don't pickle if it's already ok + if object and object == self.object: + return + + # don't pickle if there is no path + if not self._path: + return + + # default to pickling our object again + if object is None: + object = self.object + + # pickle + self.object = object + (fd, path) = tempfile.mkstemp(suffix='.morituri.pickle') + handle = os.fdopen(fd, 'wb') + print 'pickle' + import pickle + pickle.dump(object, handle, 2) + handle.close() + # do an atomic move + shutil.move(path, self._path) + + def _unpickle(self, default=None): + self.object = default + + if not self._path: + return None + + if not os.path.exists(self._path): + return None + + handle = open(self._path) + import pickle + print 'unpickle' + self.object = pickle.load(handle)