home *** CD-ROM | disk | FTP | other *** search
/ PC Welt 2006 November (DVD) / PCWELT_11_2006.ISO / casper / filesystem.squashfs / usr / lib / python2.4 / site-packages / serpentine / components.py < prev    next >
Encoding:
Python Source  |  2006-08-23  |  6.1 KB  |  186 lines

  1. # -*- coding: utf-8 -*-
  2. # Copyright (C) 2005 Tiago Cogumbreiro <cogumbreiro@users.sf.net>
  3. # $Id: components.py 570 2005-09-09 19:28:26Z cogumbreiro $
  4.  
  5. #Permission is hereby granted, free of charge, to any person obtaining a copy
  6. #of this software and associated documentation files (the "Software"), to deal
  7. #in the Software without restriction, including without limitation the rights
  8. #to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  9. #copies of the Software, and to permit persons to whom the Software is
  10. #furnished to do so, subject to the following conditions:
  11. #
  12. #The above copyright notice and this permission notice shall be included in
  13. #all copies or substantial portions of the Software.
  14. #
  15. #THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. #IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. #FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18. #AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. #LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20. #OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  21. #SOFTWARE.
  22.  
  23. import weakref
  24.  
  25. void_method = lambda self: None
  26. void_func = lambda *args: None
  27.  
  28. def getRootComponent(component):
  29.     """
  30.     This is a helper function that tranverses the component tree upwards.
  31.     """
  32.     while component.parent is not None:
  33.         component = component.parent
  34.     return component
  35.  
  36. class ObjectPath (object):
  37.     """
  38.     An ObjectPath binds the path to a certain attribute to the instance
  39.     of this class. It can have a relative or a absolute path, example:
  40.     class Foo(Component):
  41.         a_dict = {}
  42.         a_list = []
  43.         
  44.         grandparent = ObjectPath ("../..")
  45.         root = ObjectPath ("/", static=True)
  46.         a_list_count = ObjectPath("a_list.__len__()")
  47.     
  48.     You can navigate up the hierarchy if you use the '..' fragment, this
  49.     assumes your object has a field named 'parent'.
  50.     
  51.     You can also call any callable fragment using "()".
  52.     
  53.     If you assign the 'static' keyword argument to True then the
  54.     value is only retrieved once.
  55.     """
  56.     def __init__ (self, path, static = False):
  57.         self.fullPath = path.split("/")
  58.         self.isAbsolute = path.startswith("/")
  59.         self.isStatic = static
  60.     
  61.     def transverse (self, full_path, helper_func):
  62.         
  63.         return obj
  64.         
  65.     def __get__ (self, obj, type = None):
  66.  
  67.         if self.isStatic and hasattr(self, "returnValue"):
  68.             return self.returnValue
  69.             
  70.         if self.isAbsolute:
  71.             obj = getRootComponent(obj)
  72.             
  73.         for path in self.fullPath:
  74.             if path == "." or path == "":
  75.                 pass
  76.             elif path == "..":
  77.                 obj = obj.parent
  78.             else:
  79.                 is_callable = path.endswith("()")
  80.                 if is_callable:
  81.                     path = path[:-len ("()")]
  82.                 
  83.                 obj = getattr(obj, path)
  84.                 if is_callable:
  85.                     obj = obj()
  86.         
  87.         if self.isStatic:
  88.             self.returnValue = obj
  89.             
  90.         return obj
  91.  
  92. class PropertyWrapper (object):
  93.     """
  94.     PropertyWrapper is usefull to wrap the getter and setter methods of a
  95.     variable that is not accessible through the 'property' protocol.
  96.     It accepts private variables as well. 
  97.     """
  98.     def __init__ (self, variable, getter = None, setter = None):
  99.         self.variable = variable
  100.         self.realVariable = None
  101.         self.getter = getter
  102.         self.setter = setter
  103.         
  104.         if self.setter is None:
  105.             del self.__set__
  106.         
  107.         if self.getter is None:
  108.             del self.__get__
  109.         
  110.     def getVariable (self, obj):
  111.         if self.realVariable is None:
  112.             if self.variable.startswith("__"):
  113.                 self.realVariable = "_" + type(obj).__name__ + self.variable
  114.             else:
  115.                 self.realVariable = self.variable
  116.         return getattr (obj, self.realVariable)
  117.     
  118.     def __get__ (self, obj, type = None):
  119.         obj = self.getVariable (obj)
  120.         return getattr (obj, self.getter)()
  121.     
  122.     def __set__ (self, obj, value):
  123.         obj = self.getVariable (obj)
  124.         getattr (obj, self.setter) (value)
  125.  
  126. class LazyComponent (object):
  127.     """
  128.     A 'LazyComponent' is created only when it's needed. It should wrap the
  129.     component that you want to make lazy.
  130.     
  131.     Usage example:
  132.     
  133.     class Bar (Component):
  134.         pass
  135.     
  136.     class Foo (Component):
  137.         bar = LazyComponent (Bar)
  138.     
  139.     When you create an instance of 'Foo', the 'bar' instance will only be
  140.     created when you access it the first time.    
  141.     """
  142.     
  143.     def __init__ (self, componentFactory):
  144.         self.componentFactory = componentFactory
  145.         
  146.     def __get__ (self, obj, type = None):
  147.         if hasattr (self, "component"):
  148.             return self.component
  149.         
  150.         self.component = self.componentFactory (obj)
  151.         return self.component
  152.  
  153. class Component (object):
  154.     """
  155.     A Component is an object that is structured in a hierarchical model.
  156.     It is constructed upon runtime from the root to its children. To define
  157.     a Component you have to define a list of subcomponents, these are usually
  158.     classes of this type.
  159.     They define a method called '_init' that is called in the constructor.
  160.     It also contains a '_components' protected variable that holds a list of its
  161.     children components.
  162.     """
  163.     
  164.     def __init__ (self, parent = None):
  165.         self.__parent = parent is not None and weakref.ref (parent) or void_func
  166.         # Maintain components reference
  167.         self._components = []
  168.         for component in self.components:
  169.             self._components.append (component(self))
  170.         
  171.         for attr, component in self.namedComponents.iteritems ():
  172.             setattr (self, attr, component(self))
  173.         self._init ()
  174.     
  175.     def _init (self):
  176.         """Override this method which is called in the constructor."""
  177.     
  178.     def getParent (self):
  179.         return self.__parent ()
  180.         
  181.     parent = property (getParent)
  182.     
  183.     components = ()
  184.     namedComponents = {}
  185.  
  186.