GnuCash 2.4.99
function_class.py
Go to the documentation of this file.
00001 # function_class.py -- Library for making python classes from a set
00002 #                      of functions. 
00003 #
00004 # Copyright (C) 2008 ParIT Worker Co-operative <paritinfo@parit.ca>
00005 # This program is free software; you can redistribute it and/or
00006 # modify it under the terms of the GNU General Public License as
00007 # published by the Free Software Foundation; either version 2 of
00008 # the License, or (at your option) any later version.
00009 #
00010 # This program is distributed in the hope that it will be useful,
00011 # but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 # GNU General Public License for more details.
00014 #
00015 # You should have received a copy of the GNU General Public License
00016 # along with this program; if not, contact:
00017 # Free Software Foundation           Voice:  +1-617-542-5942
00018 # 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652
00019 # Boston, MA  02110-1301,  USA       gnu@gnu.org
00020 #
00021 # @author Mark Jenkins, ParIT Worker Co-operative <mark@parit.ca>
00022 
00023 ##  @file
00024 #   @brief Library for making python classes from a set of functions.
00025 #   @author Mark Jenkins, ParIT Worker Co-operative <mark@parit.ca>
00026 #   @author Jeff Green,   ParIT Worker Co-operative <jeff@parit.ca>
00027 #   @ingroup python_bindings
00028 
00029 INSTANCE_ARGUMENT = "instance"
00030 
00031 class ClassFromFunctions(object):
00032     """Inherit this class to give yourself a python class that wraps a set of
00033     functions that together constitute the methods of the class.
00034 
00035     The method functions must all have as a first argument an object
00036     holding the instance data. There must also be a function that
00037     returns a new instance of the class, the constructor.
00038 
00039     Your subclass must define
00040     _module - The module where the method functions, including the
00041     constructor can be found
00042     _new_instance - The name of a function that serves as a constructor,
00043     returning the instance data.
00044 
00045     To access the instance data, use the read-only property instance.
00046 
00047     To add some functions from _module as methods, call classmethods like
00048     add_method and add_methods_with_prefix.
00049     """
00050     def __new__(cls, *args, **kargs):
00051         # why reimpliment __new__? Because later on we're going to
00052         # use new to avoid creating new instances when existing instances
00053         # already exist with the same __instance value, or equivalent __instance
00054         # values, where this is desirable...
00055         return super(ClassFromFunctions, cls).__new__(cls)
00056     
00057     def __init__(self, *args, **kargs):
00058         """Construct a new instance, using either the function
00059         self._module[self._new_instance] or using existing instance
00060         data. (specified with the keyword argument, instance)
00061 
00062         Pass the arguments that should be passed on to
00063         self._module[self._new_instance] . Any arguments of that
00064         are instances of ClassFromFunctions will be switched with the instance
00065         data. (by calling the .instance property)
00066         """
00067         if INSTANCE_ARGUMENT in kargs:
00068             self.__instance = kargs[INSTANCE_ARGUMENT]
00069         else:
00070             self.__instance = getattr(self._module, self._new_instance)(
00071                 *process_list_convert_to_instance(args) )
00072 
00073     def get_instance(self):
00074         """Get the instance data.
00075 
00076         You can also call the instance property
00077         """
00078         return self.__instance
00079 
00080     instance = property(get_instance)
00081 
00082     # CLASS METHODS
00083 
00084     @classmethod
00085     def add_method(cls, function_name, method_name):
00086         """Add the function, method_name to this class as a method named name
00087         """
00088         def method_function(self, *meth_func_args):
00089             return getattr(self._module, function_name)(
00090                 self.instance,
00091                 *process_list_convert_to_instance(meth_func_args) )
00092         
00093         setattr(cls, method_name, method_function)
00094         setattr(method_function, "__name__", method_name)
00095         return method_function
00096 
00097     @classmethod
00098     def ya_add_classmethod(cls, function_name, method_name):
00099         """Add the function, method_name to this class as a classmethod named name
00100         
00101         Taken from function_class and slightly modified.
00102         """
00103         def method_function(self, *meth_func_args):
00104             return getattr(self._module, function_name)(
00105                 self,
00106                 *process_list_convert_to_instance(meth_func_args) )
00107         
00108         setattr(cls, method_name, classmethod(method_function))
00109         setattr(method_function, "__name__", method_name)
00110         return method_function    
00111 
00112     @classmethod
00113     def ya_add_method(cls, function_name, method_name):
00114         """Add the function, method_name to this class as a method named name
00115         
00116         Taken from function_class and slightly modified.
00117         """
00118         def method_function(self, *meth_func_args):
00119             return getattr(self._module, function_name)(
00120                 self,
00121                 *process_list_convert_to_instance(meth_func_args) )
00122         
00123         setattr(cls, method_name, method_function)
00124         setattr(method_function, "__name__", method_name)
00125         return method_function
00126 
00127     @classmethod
00128     def add_methods_with_prefix(cls, prefix):
00129         """Add a group of functions with the same prefix 
00130         """
00131         for function_name, function_value, after_prefix in \
00132             extract_attributes_with_prefix(cls._module, prefix):
00133                 cls.add_method(function_name, after_prefix)
00134     
00135     @classmethod
00136     def add_constructor_and_methods_with_prefix(cls, prefix, constructor):
00137         """Add a group of functions with the same prefix, and set the
00138         _new_instance attribute to prefix + constructor
00139         """
00140         cls.add_methods_with_prefix(prefix)
00141         cls._new_instance = prefix + constructor
00142 
00143     @classmethod
00144     def decorate_functions(cls, decorator, *args):
00145         for function_name in args:
00146             setattr( cls, function_name,
00147                      decorator( getattr(cls, function_name) ) )
00148 
00149 def method_function_returns_instance(method_function, cls):
00150     """A function decorator that is used to decorate method functions that
00151     return instance data, to return instances instead.
00152 
00153     You can't use this decorator with @, because this function has a second
00154     argument.
00155     """
00156     assert( 'instance' == INSTANCE_ARGUMENT )
00157     def new_function(*args):
00158         kargs = { INSTANCE_ARGUMENT : method_function(*args) }
00159         return cls( **kargs )
00160     
00161     return new_function
00162 
00163 def method_function_returns_instance_list(method_function, cls):
00164     def new_function(*args):
00165         return [ cls( **{INSTANCE_ARGUMENT: item} )
00166                  for item in method_function(*args) ]
00167     return new_function
00168 
00169 def methods_return_instance_lists(cls, function_dict):
00170     for func_name, instance_name in function_dict.iteritems():
00171         setattr(cls, func_name,
00172                 method_function_returns_instance_list(
00173                 getattr(cls, func_name), instance_name))
00174 
00175 def default_arguments_decorator(function, *args):
00176     """Decorates a function to give it default, positional arguments
00177 
00178     You can't use this decorator with @, because this function has more
00179     than one argument.
00180     """
00181     def new_function(*function_args):
00182         new_argset = list(function_args)
00183         new_argset.extend( args[ len(function_args): ] )
00184         return function( *new_argset )
00185     return new_function
00186     
00187 def return_instance_if_value_has_it(value):
00188     """Return value.instance if value is an instance of ClassFromFunctions,
00189     else return value
00190     """
00191     if isinstance(value, ClassFromFunctions):
00192         return value.instance
00193     else:
00194         return value
00195 
00196 def process_list_convert_to_instance( value_list ):
00197     """Return a list built from value_list, where if a value is in an instance
00198     of ClassFromFunctions, we put value.instance in the list instead.
00199 
00200     Things that are not instances of ClassFromFunctions are returned to
00201     the new list unchanged.
00202     """
00203     return [ return_instance_if_value_has_it(value)
00204              for value in value_list ]
00205 
00206 def extract_attributes_with_prefix(obj, prefix):
00207     """Generator that iterates through the attributes of an object and
00208     for any attribute that matches a prefix, this yields
00209     the attribute name, the attribute value, and the text that appears
00210     after the prefix in the name
00211     """
00212     for attr_name, attr_value in obj.__dict__.iteritems():
00213         if attr_name.startswith(prefix):
00214             after_prefix = attr_name[ len(prefix): ]
00215             yield attr_name, attr_value, after_prefix
00216 
00217 def methods_return_instance(cls, function_dict):
00218     """Iterates through a dictionary of function name strings and instance names
00219     and sets the function to return the associated instance 
00220     """
00221     for func_name, instance_name in function_dict.iteritems():
00222         setattr(cls, func_name, 
00223             method_function_returns_instance( getattr(cls, func_name), instance_name))
00224 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines