00001 """
00002 environment settings for all of slimpy
00003 """
00004
00005 __copyright__ = """
00006 Copyright 2008 Sean Ross-Ross
00007 """
00008 __license__ = """
00009 This file is part of SLIMpy .
00010
00011 SLIMpy is free software: you can redistribute it and/or modify
00012 it under the terms of the GNU Lesser General Public License as published by
00013 the Free Software Foundation, either version 3 of the License, or
00014 (at your option) any later version.
00015
00016 SLIMpy is distributed in the hope that it will be useful,
00017 but WITHOUT ANY WARRANTY; without even the implied warranty of
00018 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00019 GNU Lesser General Public License for more details.
00020
00021 You should have received a copy of the GNU Lesser General Public License
00022 along with SLIMpy . If not, see <http://www.gnu.org/licenses/>.
00023 """
00024
00025
00026 from thread import get_ident
00027
00028 def thread_landmark():
00029 'returns the thread id'
00030 return get_ident()
00031
00032 class InstanceManager( object ):
00033 '''
00034 manages instance with a landmak function
00035
00036 '''
00037 _shared_state = { }
00038 singletons = dict()
00039 non_singletons = dict()
00040 _ns_map = dict()
00041 _lm_map = { }
00042 _lm_count = 0
00043
00044 _rank = []
00045
00046 def __str__( self ):
00047 return "InstanceManager<default=%s>" %self.get_env()
00048
00049 def get_count( self ):
00050 'returns the number of dirrent keys the lanmark has returned'
00051 InstanceManager._lm_count += 1
00052 return InstanceManager._lm_count
00053
00054 count = property( get_count )
00055
00056 def __init__( self ):
00057 self.__dict__ = self._shared_state
00058
00059 def set_schema( self, schematic ):
00060 'not implemented'
00061 pass
00062
00063 def __iter__( self ):
00064 'returns a list of the names of the singleton classes'
00065 for key in self.singletons:
00066 yield self[key]
00067 return
00068
00069 def __getitem__( self, item ):
00070 '''
00071 returns an singleton instance
00072 env[name] <==> env.get_singleton(name)
00073 '''
00074 Class = self.singletons[item]
00075
00076 landmark_id = self.landmark()
00077
00078 instance_id = self.map( landmark_id )
00079
00080 instance = Class( instance_id )
00081
00082 return instance
00083
00084 def get_singleton( self, item ):
00085 'same as env.get_singleton(name) <==> env[name]'
00086 Class = self.singletons[item]
00087
00088 landmark_id = self.landmark()
00089
00090 insnace_id = self.map( landmark_id )
00091
00092 instance = Class( insnace_id )
00093
00094 return instance
00095
00096 def get_non_singleton( self, name ):
00097 'return non singleton class managed by this'
00098 cur_env = self.current_env
00099
00100 env_map = self._ns_map[name]
00101
00102 ns = self.non_singletons[name]
00103
00104 if not env_map.has_key( cur_env ):
00105 obj = ns['obj']
00106 p = ns['p']
00107 kw = ns['kw']
00108
00109 non_single = obj( *p, **kw )
00110 else:
00111 non_single = env_map[cur_env]
00112
00113 return non_single
00114
00115
00116 def map( self, landmark_id ):
00117 """return the current landmark id
00118 as env#
00119 """
00120 if landmark_id not in self._lm_map:
00121 self._lm_map[ landmark_id ] = "env%s" %self.count
00122 return self._lm_map[ landmark_id ]
00123
00124 def _get_lm( self ):
00125 'returns landmark function'
00126 return self._lm_map.keys()
00127
00128 lms = property( _get_lm )
00129
00130 def _get_instance_names( self ):
00131 'returns all of the evironments that where instanciated so far'
00132 return set( self._lm_map.values() )
00133
00134 instance_names = property( _get_instance_names )
00135
00136 def __setitem__( self, item, value ):
00137 "add a singleton class"
00138 self.singletons[item] = value
00139
00140 self._rank.append( item )
00141
00142 def set_landmark( self, lm ):
00143 'set landmark function'
00144 self._landmark = lm
00145 return
00146
00147 def get_landmark( self ):
00148 'returns landmark function'
00149 if not hasattr( self, "_landmark" ):
00150 return thread_landmark
00151 else:
00152 return self._landmark
00153
00154 def set( self, lm, name ):
00155 """
00156 should use set_env instead
00157 set the mapping for landmark
00158 used to mark instances that should be the same but are not
00159 example:
00160 if the landmark is by thread, then
00161 to map two theads to the same instance
00162 then
00163 call:
00164 set( thread1_id, "newname")
00165 set( thread2_id, "newname")
00166
00167 """
00168 self._lm_map[ lm ] = name
00169
00170 def set_env( self, name ):
00171 """
00172 set an environment name in the map
00173 if instances have already been created with a
00174 old name then
00175 """
00176 landmark_id = self.landmark()
00177
00178 if self._lm_map.has_key( landmark_id ):
00179 if not self._lm_map[landmark_id] == name:
00180 raise Exception( "environment already set" )
00181 else:
00182 return
00183
00184 self._lm_map[ self.landmark() ] = name
00185
00186 def get_env( self ):
00187 '''
00188 returns the current env name
00189 '''
00190 landmark_id = self.landmark()
00191 return self.map( landmark_id )
00192
00193 landmark = property( get_landmark, set_landmark )
00194 current_env = property( get_env, set_env )
00195
00196
00197 def __delitem__(self,instance_name):
00198 self.del_instance( instance_name )
00199
00200 def del_instance( self, instance_name ):
00201 """
00202 delete the instance 'instance_name' from each
00203 singleton stored
00204 """
00205
00206 for key in self._rank:
00207 singleton_class = self.singletons[key]
00208 singleton_class( instance_name ).__clean__()
00209 singleton_class.__del_instance__( instance_name )
00210
00211 for key, val in self._lm_map.iteritems():
00212 if val == instance_name:
00213 self._lm_map.pop( key )
00214 break
00215
00216 return
00217
00218 def assure_new_instances( self ):
00219 """
00220 calls the __new_instance__ class for each of the
00221 classes stored
00222 """
00223 for key in self._rank:
00224 self[key]
00225
00226 return
00227
00228 def manage_non_singleton( self, name, obj, *p, **kw ):
00229 """
00230 add a non-singleton class, treats it like a singleton
00231 """
00232 self.non_singletons[name] = { 'obj': obj, 'p':p, 'kw':kw }
00233
00234
00235
00236 env_map = self._ns_map.setdefault( name, {} )
00237 env_map[self.current_env] = obj( *p, **kw )
00238
00239 def Execute(self):
00240 return self.End()
00241 def End( self ):
00242 """
00243 calls 'End' on each singleton class before calling
00244 __del_instance__
00245 """
00246 current_env = self.current_env
00247
00248 for instance in self:
00249 if hasattr( instance, "End" ):
00250 instance.End()
00251
00252 self.del_instance( current_env )
00253 self.assure_new_instances()
00254
00255 def reset( self ):
00256 current_env = self.current_env
00257 self.del_instance( current_env )
00258 self.assure_new_instances()