At Sat, 18 Jun 2011 23:43:15 +0200, Neal H. Walfield wrote: > model.py would become responsible for managing object lifetimes. I > propose that channels and episodes become singletons and that weak > references be used to avoid having the whole DB in memory.
The attached patch implements this. I've tested this using the GTK frontend. A possible improvement would be only free objects if they haven't been referenced for a few minutes. As far as I can tell, python does not support this out of the box and adding it appears non-trivial. Further, adding it requires the ability to schedule a callback in the future. Does model.py assume that glib or qt is available? Thanks, Neal >From 1fcbfe9d6a8fa87024a304c5a59edee14b52d767 Mon Sep 17 00:00:00 2001 From: Neal H. Walfield <[email protected]> Date: Mon, 20 Jun 2011 17:48:36 +0200 Subject: [PATCH] Make podcasts and episodes singletons. - Manage the singletons using weak references to limit memory use. --- src/gpodder/model.py | 49 +++++++++++++++++++++++++++++++++++++++++++------ 1 files changed, 43 insertions(+), 6 deletions(-) diff --git a/src/gpodder/model.py b/src/gpodder/model.py index fd0d5a3..85df996 100644 --- a/src/gpodder/model.py +++ b/src/gpodder/model.py @@ -39,6 +39,7 @@ import datetime import rfc822 import hashlib import feedparser +from weakref import WeakValueDictionary _ = gpodder.gettext @@ -82,28 +83,64 @@ class PodcastModelObject(object): """ A generic base class for our podcast model providing common helper and utility functions. - """ + PodcastEpisode and PodcastChannel inherit from this class to + facilitate instantiation and wholesale updates of attributes. + + This base class also ensures that only a single instance of an + object with the same type and id exists. + """ @classmethod def create_from_dict(cls, d, *args): """ - Create a new object, passing "args" to the constructor - and then updating the object with the values from "d". + Return the python object for the object instance of tyep cls + with id d['id']. + + If the object does not yet exist, instantiates it and passes + "args" to the constructor. + + Update the object's attributes with the values from "d". """ - o = cls(*args) + assert 'id' in d + + if not hasattr (cls, '_singletons'): + cls._singletons = WeakValueDictionary() + + o = cls._singletons.get ('id', None) + if o is None: + o = cls(*args) + o.update_from_dict(d) + return o + def __setattr__(self, name, value): + """ + If changing the id attribute, update the singleton map + appropriately. Either way, set the attribute as usual. + """ + if name == 'id': + old_value = self.__class__.__dict__.get ('id', None) + if value != old_value: + # The identity changed. Move the singleton. + if old_value is not None: + del self.__class__._singletons[old_value] + if value is not None: + self.__class__._singletons[value] = self + + super (PodcastModelObject, self).__setattr__ (name, value) + def update_from_dict(self, d): """ Updates the attributes of this object with values from the - dictionary "d" by using the keys found in "d". + dictionary "d" by using the keys found in "d". Any keys in + "d" that are not attributes of the object are silently + ignored. """ for k in d: if hasattr(self, k): setattr(self, k, d[k]) - class PodcastEpisode(PodcastModelObject): """holds data for one object in a channel""" MAX_FILENAME_LENGTH = 200 -- 1.7.2.5 _______________________________________________ gpodder-devel mailing list [email protected] https://lists.berlios.de/mailman/listinfo/gpodder-devel
