00001 """
00002 Class to be used by plug-ins
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 slimpy_base.Core.Command.CommandPack import CommandPack
00027 from slimpy_base.Environment.InstanceManager import InstanceManager
00028 from slimpy_base.Core.Interface.PSpace import voidSpace
00029
00030 __env__ = InstanceManager()
00031
00032 class ConstraintFunctions( object ):
00033 """
00034 Class containing classmethod methods to
00035 use in the constraint definitions of
00036 plug-in commands
00037 """
00038
00039 @classmethod
00040 def match( cls, params, *keys, **kargs ):
00041 """
00042 match args to params and if keyword args are specified
00043 match the values as well
00044 """
00045 msg = "Space does not have key %(key)s"
00046
00047 for key in keys:
00048 if not params.has_key( key ):
00049 raise TypeError( msg %vars() )
00050
00051 for key in kargs:
00052 if not params.has_key( key ):
00053 raise TypeError( msg %vars() )
00054
00055 elif params[key] != kargs[key]:
00056 raise TypeError( "space restriction space[%s]=%s failed, got =%s "
00057 %(repr(key) , kargs[key], params[key] ) )
00058
00059
00060 @classmethod
00061 def eqType( cls, command, params ):
00062 """
00063 test if all of the spaces given are of
00064 equal shape.
00065 """
00066
00067 def assert_has_data_type( spc ):
00068 if spc.has_key( 'data_type' ):
00069 pass
00070 else:
00071 msg = "The parameter object %(spc)s does not have a data_type"
00072 raise TypeError( msg %vars() )
00073
00074 assert_has_data_type( params[0] )
00075
00076 pre = params[0]["data_type"]
00077 for s_spc in params:
00078 assert_has_data_type( s_spc )
00079 new = s_spc['data_type']
00080 if not pre == new:
00081 msg = "need equal data type: %(pre)s != %(new)s"
00082 raise TypeError( msg %vars() )
00083
00084 @classmethod
00085 def shape( cls, space ):
00086 n_val = 1
00087 key = "n%(n_val)s" %vars()
00088 shp = []
00089 while space.has_key( key ):
00090 shp.append( space[key] )
00091 n_val += 1
00092 key = "n%(n_val)s" %vars()
00093
00094 n_val -= 2
00095 while n_val and shp[n_val] == 1:
00096 shp.pop()
00097 n_val -= 1
00098 return shp
00099
00100 @classmethod
00101 def eqShape( cls, command, params ):
00102 """
00103 raise a TypeError if the param/Space instances in params
00104 are not of equal type
00105 """
00106
00107
00108 shapes = [ par.shape for par in params ]
00109
00110
00111
00112 z = zip( *shapes )
00113 for l in z:
00114 item = l[0]
00115 for i in l:
00116 if not item == i:
00117 raise TypeError( "Shape Mismatch %s" % " != ".join(map(repr,shapes)) )
00118
00119 return
00120
00121
00122 @classmethod
00123 def eqVectorType( cls, *spaces ):
00124 """
00125 TODO:
00126 """
00127 vt = spaces[0].vector_type
00128 for s in spaces:
00129 if not s.vector_type == vt:
00130 raise TypeError( "TODO: doc" )
00131 return True
00132
00133
00134
00135 class MapFunctions( object ):
00136 """
00137 methods for helping the mapping of generic SLIMpy
00138 commands to a specific plug-in command
00139 """
00140
00141 @classmethod
00142 def pack( cls, command , stdin=True, stdout=True ):
00143 """
00144 pack a source, command and target into
00145 a CommandPack instance
00146 @return: CommandPack instance
00147 """
00148 if isinstance( command, (tuple, list) ):
00149 comm = command
00150 else:
00151 comm = [command]
00152
00153 return CommandPack( comm, stdin, stdout )
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169 @classmethod
00170 def keep( cls, command, keywords ):
00171 """
00172 keeps only the keywords in cmnd
00173 """
00174 for key in command.kparams.keys():
00175 if key not in keywords:
00176 command.kparams.pop( key )
00177
00178 return command
00179 @classmethod
00180 def discard( cls, command, keywords ):
00181 """
00182 discards all of keywords found in cmnd
00183 """
00184 for key in keywords:
00185 command.kparams.pop( key, None )
00186
00187 return command
00188
00189 @classmethod
00190 def keywordmap( cls, command, Dict ):
00191
00192 """
00193 maps keys in the kparams dictionary to the
00194 the value of the key in the mapDict
00195 note that if the key 'a' maps to 'b'
00196 and 'b' is already defined then the behavior becomes unpredictable
00197
00198 """
00199
00200 kparams = command.kparams
00201 for key in kparams.keys():
00202 if Dict.has_key( key ):
00203 kparams[ Dict[key] ] = kparams[key]
00204 kparams.pop( key )
00205
00206 return command
00207
00208 @classmethod
00209 def split( cls, command ):
00210 """
00211 split the command into 2 identical copies
00212 """
00213 command1 = command.copy()
00214 command2 = command.copy()
00215 return command1, command2
00216
00217 @classmethod
00218 def truefalseHelper( cls, command, true='y', false='n' ):
00219 """
00220 convert python boolean True/False values
00221 to 'y'/'n' strings
00222 """
00223
00224 kparams = command.kparams
00225
00226 for key in kparams.keys():
00227 if kparams[key] is True:
00228 kparams[key] = true
00229 elif kparams[key] is False:
00230 kparams[key] = false
00231
00232 return command
00233
00234
00235 class TransformFunctions( object ):
00236 """
00237 Helper methods for transformation of spaces
00238 to the resulting spaces of a command
00239 """
00240 @classmethod
00241 def change( cls, space, *d, **k ):
00242 """
00243 update the space with dict d or keyword arguments
00244 """
00245 space.update( *d, **k )
00246 return space
00247
00248 class Converter( ConstraintFunctions, MapFunctions, TransformFunctions ):
00249 """
00250 class is subclass of 'ConstraintFunctions',
00251 'MapFunctions' and 'TransformFunctions'
00252 for one convenience class
00253
00254 """
00255 def __init__( self ):
00256 pass
00257
00258 @classmethod
00259 def apply_command( cls, command, source):
00260 strict_check = __env__['slimvars']['strict_check']
00261
00262
00263
00264 if strict_check > 0:
00265 cls.constrain( command, source.params )
00266
00267
00268
00269
00270 newspace = cls.transform( command, source.params )
00271
00272 compack = cls.convert( source, command )
00273
00274 if strict_check > 1:
00275 if isinstance( newspace, voidSpace ):
00276 msg = ( "'strict_check >= 2' prevents commands "
00277 "from returning voidSpace\n"
00278 "command '%(command)s' returned voidSpace" %vars() )
00279 raise Exception( msg )
00280
00281 newcontainer = newspace.makeContaner( command=command )
00282
00283
00284
00285 return compack, newcontainer
00286
00287 @classmethod
00288 def convert( cls, source, command ):
00289 """
00290 Used internally by SLIMy.Core.Interface sub-package
00291 calls regex - map.* - of subclasses
00292 """
00293 method = cls.getmatch( command, 'map_' )
00294 result = method( source, command.copy() )
00295 if not isinstance( result, CommandPack ):
00296 msg = "converter function '%(method)s' did not return a CommandPack instance " % vars()
00297 raise Exception( msg )
00298 return result
00299
00300 @classmethod
00301 def transform( cls, command, space ):
00302 """
00303 Used internally by SLIMy.Core.Interface sub-package
00304 calls regex - trans.* - of subclasses
00305 """
00306 space = space.copy( )
00307 spaces = [ space ] + command.get_source_spaces( )
00308 method = cls.getmatch( command, 'trans_' )
00309 result = method( command, space, *spaces )
00310
00311 if result is None:
00312 raise TypeError( "'$(method)s' did not return a Parameter object, got '%(result)s'" %vars() )
00313 return result
00314
00315 @classmethod
00316 def constrain( cls, command, Space ):
00317 """
00318 Used internally by SLIMy.Core.Interface sub-package
00319 calls regex - constr.* - of subclasses
00320 """
00321
00322 method = cls.getmatch( command, 'constr_' )
00323 return method( command, Space )
00324
00325
00326 @classmethod
00327 def map( cls, source, command ):
00328 """
00329 default mapping 1 to 1
00330 """
00331 return CommandPack( [command] )
00332
00333 @classmethod
00334 def trans( cls, command, space, *spaces ):
00335 """
00336 default trans, returns voidSpace
00337 """
00338 from slimpy_base.Core.Interface.PSpace import voidSpace
00339 return voidSpace( space.plugin )
00340
00341
00342 @classmethod
00343 def getmatch( cls, command, prefix ):
00344 """
00345 helper method to match
00346 """
00347 lp = len( prefix )
00348 isp = lambda item: item[lp:].split( '_' )
00349
00350 items = [ isp( item ) for item in dir( cls )
00351 if item.startswith( prefix ) ]
00352
00353
00354
00355
00356 lcmp = lambda a1, b1: cmp( len( a1 ), len( b1 ) )
00357 items.sort( lcmp, reverse=True )
00358
00359 for func_keys in items:
00360
00361
00362 if all_in( func_keys, command ):
00363 method = prefix + "_".join( func_keys )
00364 return getattr( cls, method )
00365
00366 return getattr( cls, prefix[:-1] )
00367
00368 def all_in( func_keys, command ):
00369 """
00370 returns true if all of the strings in func_keys
00371 are also in command and the values of the keys are
00372 True --or-- if command does not have the key but
00373 the value is true in SLIMpy.GlobalVars
00374 """
00375 slimvars = __env__['slimvars']
00376 for fkey in func_keys:
00377 if fkey in command:
00378 if command[fkey]:
00379 continue
00380 else:
00381 return False
00382 elif fkey in slimvars and slimvars[fkey]:
00383 continue
00384 else:
00385 return False
00386
00387 return True
00388
00389
00390
00391