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

Reply via email to