huge use of weakrefs to remove memoryleaks due to circular references
[tiramisu.git] / tiramisu / config.py
index 1d7beca..a0c3982 100644 (file)
@@ -20,6 +20,7 @@
 # the rough pypy's guys: http://codespeak.net/svn/pypy/dist/pypy/config/
 # the whole pypy projet is under MIT licence
 # ____________________________________________________________
+import weakref
 from tiramisu.error import PropertiesOptionError, ConfigError
 from tiramisu.option import OptionDescription, Option, SymLinkOption, \
     BaseInformation
@@ -47,14 +48,14 @@ class SubConfig(BaseInformation):
                               ).format(type(descr)))
         self._impl_descr = descr
         # sub option descriptions
-        if not isinstance(context, SubConfig):
-            raise ValueError('context must be a SubConfig')
+        if not isinstance(context, weakref.ReferenceType):
+            raise ValueError('context must be a Weakref')
         self._impl_context = context
         self._impl_path = subpath
 
     def cfgimpl_reset_cache(self, only_expired=False, only=('values',
                                                             'settings')):
-        self.cfgimpl_get_context().cfgimpl_reset_cache(only_expired, only)
+        self._cfgimpl_get_context().cfgimpl_reset_cache(only_expired, only)
 
     def cfgimpl_get_home_by_path(self, path, force_permissive=False,
                                  force_properties=None):
@@ -148,8 +149,8 @@ class SubConfig(BaseInformation):
 
     __repr__ = __str__
 
-    def cfgimpl_get_context(self):
-        return self._impl_context
+    def _cfgimpl_get_context(self):
+        return self._impl_context()
 
     def cfgimpl_get_description(self):
         if self._impl_descr is None:
@@ -159,10 +160,10 @@ class SubConfig(BaseInformation):
             return self._impl_descr
 
     def cfgimpl_get_settings(self):
-        return self.cfgimpl_get_context()._impl_settings
+        return self._cfgimpl_get_context()._impl_settings
 
     def cfgimpl_get_values(self):
-        return self.cfgimpl_get_context()._impl_values
+        return self._cfgimpl_get_context()._impl_values
 
     # ____________________________________________________________
     # attribute methods
@@ -186,7 +187,7 @@ class SubConfig(BaseInformation):
             self.cfgimpl_get_values().setitem(child, value, path,
                                               force_permissive=force_permissive)
         else:
-            context = self.cfgimpl_get_context()
+            context = self._cfgimpl_get_context()
             path = context.cfgimpl_get_description().impl_get_path_by_opt(
                 child._opt)
             context._setattr(path, value, force_permissive=force_permissive)
@@ -222,7 +223,7 @@ class SubConfig(BaseInformation):
             subpath = self._impl_path + '.' + name
         # symlink options
         if isinstance(opt_or_descr, SymLinkOption):
-            context = self.cfgimpl_get_context()
+            context = self._cfgimpl_get_context()
             path = context.cfgimpl_get_description().impl_get_path_by_opt(
                 opt_or_descr._opt)
             return context._getattr(path, validate=validate,
@@ -233,7 +234,7 @@ class SubConfig(BaseInformation):
                 opt_or_descr, True, False, path=subpath,
                 force_permissive=force_permissive,
                 force_properties=force_properties)
-            return SubConfig(opt_or_descr, self.cfgimpl_get_context(), subpath)
+            return SubConfig(opt_or_descr, self._impl_context, subpath)
         else:
             return self.cfgimpl_get_values().getitem(
                 opt_or_descr, path=subpath,
@@ -250,7 +251,7 @@ class SubConfig(BaseInformation):
             :param byvalue: filter by the option's value
             :returns: list of matching Option objects
         """
-        return self.cfgimpl_get_context()._find(bytype, byname, byvalue,
+        return self._cfgimpl_get_context()._find(bytype, byname, byvalue,
                                                 first=False,
                                                 type_=type_,
                                                 _subpath=self.cfgimpl_get_path()
@@ -266,7 +267,7 @@ class SubConfig(BaseInformation):
             :param byvalue: filter by the option's value
             :returns: list of matching Option objects
         """
-        return self.cfgimpl_get_context()._find(
+        return self._cfgimpl_get_context()._find(
             bytype, byname, byvalue, first=True, type_=type_,
             _subpath=self.cfgimpl_get_path(), display_error=display_error)
 
@@ -400,14 +401,14 @@ class SubConfig(BaseInformation):
                                "option"))
         if withoption is not None:
             mypath = self.cfgimpl_get_path()
-            for path in self.cfgimpl_get_context()._find(bytype=Option,
-                                                         byname=withoption,
-                                                         byvalue=withvalue,
-                                                         first=False,
-                                                         type_='path',
-                                                         _subpath=mypath):
+            for path in self._cfgimpl_get_context()._find(bytype=Option,
+                                                          byname=withoption,
+                                                          byvalue=withvalue,
+                                                          first=False,
+                                                          type_='path',
+                                                          _subpath=mypath):
                 path = '.'.join(path.split('.')[:-1])
-                opt = self.cfgimpl_get_context().cfgimpl_get_description(
+                opt = self._cfgimpl_get_context().cfgimpl_get_description(
                 ).impl_get_opt_by_path(path)
                 if mypath is not None:
                     if mypath == path:
@@ -453,7 +454,7 @@ class SubConfig(BaseInformation):
 
     def cfgimpl_get_path(self):
         descr = self.cfgimpl_get_description()
-        context_descr = self.cfgimpl_get_context().cfgimpl_get_description()
+        context_descr = self._cfgimpl_get_context().cfgimpl_get_description()
         return context_descr.impl_get_path_by_opt(descr)
 
 
@@ -504,7 +505,7 @@ class CommonConfig(SubConfig):
 # ____________________________________________________________
 class Config(CommonConfig):
     "main configuration management entry"
-    __slots__ = tuple()
+    __slots__ = ('__weakref__', )
 
     def __init__(self, descr, session_id=None, persistent=False):
         """ Configuration option management master class
@@ -522,7 +523,7 @@ class Config(CommonConfig):
         storage = get_storage(self, session_id, persistent)
         self._impl_settings = Settings(self, storage)
         self._impl_values = Values(self, storage)
-        super(Config, self).__init__(descr, self)
+        super(Config, self).__init__(descr, weakref.ref(self))
         self._impl_build_all_paths()
         self._impl_meta = None
         self._impl_informations = {}