| Classes | Job Modules | Data Objects | Services | Algorithms | Tools | Packages | Directories | Tracs |

In This Package:

__init__.py

Go to the documentation of this file.
00001 """  
00002 DybDbi python package provides access to most Dbi functionality,  
00003 with generation of classes based on .spec files and wrapping of the 
00004 python classes for easier usage,  enabling access to model objects via::
00005  
00006    from DybDbi import GCalibPmtSpec
00007    from DybDbi import *
00008 
00009 
00010 Example of introspecting the specification::
00011 
00012    sk = GCalibPmtSpec.SpecKeys().aslist()    # list of row names
00013    sk
00014      ['PmtId',
00015       'Describ',
00016       'Status',
00017      ...
00018 
00019    sl = GCalibPmtSpec.SpecList().aslod()    # list of row maps ... list-of-dict 
00020    sl
00021      [{'code2db': '',
00022        'codetype': 'int',
00023        'dbtype': 'int(11)',
00024        'description': '',
00025        'legacy': 'PMTID',
00026        'memb': 'm_pmtId',
00027        'name': 'PmtId'},
00028       ...
00029 
00030    sm = GCalibPmtSpec.SpecMap().asdod()     # map of row maps, keyed by name    dict-of-dict
00031    sm
00032          {'AfterPulseProb': {'code2db': '',
00033                              'codetype': 'double',
00034                              'dbtype': 'float',
00035                              'description': 'Probability of afterpulsing',
00036                              'legacy': 'PMTAFTERPULSE',
00037                              'memb': 'm_afterPulseProb',
00038                              'name': 'AfterPulseProb'},
00039        ...
00040 
00041    sm['TimeOffset']['description']    # access any aspect of spec "matrix" directly by name
00042         'Relative transit time offset'
00043 
00044 
00045    sk = cls.SpecKeys().aslist()
00046    sm = cls.SpecMap().asdod()
00047    for k in sk:
00048        print sm[k]
00049 
00050 
00051 
00052 """
00053 import os, pprint, inspect, logging
00054 
00055 class NullHandler(logging.Handler):
00056     def emit(self, record):
00057         pass
00058 h = NullHandler()
00059 log = logging.getLogger("DybDbi")
00060 log.addHandler(h)
00061 
00062 
00063 ## enum/function only "classes" like Dbi/SimFlag/Site/... must appear after the "real" classes that use them 
00064 __all__ = """
00065 Detector DetectorSensor
00066 ServiceMode Context Site DetectorId SimFlag TimeStamp ContextRange
00067 DbiSqlValPacket DbiValRecSet DbiTableProxyRegistry DbiValidityRec DbiSqlContext DbiCascader DbiConnection DbiStatement DbiCache DbiTableProxy Dbi
00068 DybDbi DbiCtx Ctx 
00069 """.strip().split()
00070 
00071 ## kickstarting ROOT before GaudiPython allows gbl.cout, gbl.stringstream to work, used in test_10
00072 from ROOT import TObject,TList,TMap
00073 
00074 ## make TMap and TList palatable from python ... this is not general: restricted to string keys and more
00075 TMap.__getitem__ = lambda self,k:self.GetValue(k)
00076 TMap.asdict = lambda self:dict([(str(k),self.GetValue(k)) for k in self])
00077 TList.aslist = lambda self:list([str(k) for k in self])
00078 TList.aslod = lambda self:list([k.asdict() for k in self])   ## as list of dict 
00079 TMap.asdod = lambda self:dict([(str(k),self.GetValue(k).asdict()) for k in self])  ## as dict of dict
00080 
00081 
00082   
00083 from GaudiPython import gbl
00084 _getattr = lambda n:(n,getattr(gbl,n,None) or getattr(gbl,"DayaBay::%s" % n) )
00085 clss = map(_getattr,__all__)
00086 locals().update( clss )                    ## Dbi and Context related classes 
00087 
00088 ## instances 
00089 DybDbi.Instance()           ## instanciates gDbi, does not hit DB until registry is accessed
00090 gDbi = gbl.gDbi
00091 __all__ += "gDbi".split()
00092 
00093 ## generated DbiTableRow subclasses  
00094 import genDbi
00095 dtrs = inspect.getmembers(genDbi,lambda o:inspect.isclass(o) and o.__name__[0] == 'G')
00096 locals().update( dtrs  )
00097 GNAMES = map( lambda _:_[0] , dtrs )  
00098 __all__ += GNAMES + ["GNAMES"]
00099 
00100 ## skips must be defined before wrapping generates the repr and adds properties
00101 DbiCascader.__skip__ = "Connection DbName DbNo Status StatusAsString URL TableDbNo".split()
00102 DbiValidityRec.__skip__ = "Owner Index Row RowByIndex TableProxy".split()
00103 DbiTableProxy.__skip__ = "Cascader DBProxy MetaData MetaValid RowName TableName".split()
00104 DbiTableProxyRegistry.__skip__ = "TableProxy".split()
00105 
00106 ## special handling of some attributes used in the generated repr 
00107 attfn = dict(
00108      UpdateMask=lambda obj:("UpdateMask",Ctx.StringFromMask( obj.GetUpdateMask() )),
00109            Mask=lambda obj:("Mask", Ctx.StringFromMask( obj.GetMask() )),
00110         SimMask=lambda obj:("SimMask",SimFlag.StringFromMask( obj.GetSimMask() )),
00111        SiteMask=lambda obj:("SiteMask",Site.StringFromMask( obj.GetSiteMask() )),
00112   )
00113 
00114 
00115 ## publish the CSV tools 
00116 from csvrw import CSV, Source
00117 from mapper import Mapper
00118 
00119 
00120 ## wrap Dbi classes with property accessors and repr 
00121 from wrap import Wrap
00122 for n,cls in clss:
00123     #print n
00124     Wrap.wrap(cls, attfn)
00125 
00126 ## wrap DbiTableRow subclasses and associated templated classes
00127 for n,dtr in dtrs: 
00128     #print n
00129     dtr.__skip__ = "Owner Index Row RowByIndex".split()
00130     if hasattr( dtr, 'Docstring' ):
00131         dtr.__doc__ = dtr.Docstring
00132     Wrap.wrap( dtr )
00133     Wrap.wrap( getattr(gbl, "DbiRpt<%s>" % n ) )
00134     Wrap.wrap( getattr(gbl, "DbiWrt<%s>" % n ) )
00135     
00136 def DbiCascader__getitem__(self, i ):
00137     l = self.GetNumDb()
00138     if -1 < i < l:
00139         return self.GetConnection(i)
00140     raise IndexError("out of range for index %d" % i )  
00141 DbiCascader.__getitem__ = DbiCascader__getitem__
00142 DbiCascader.__len__ = DbiCascader.GetNumDb
00143 
00144 def DbiCascader__repr__(self):
00145     smry = "DbiCascader numdb %s authorisingdbno %s (1st with GLOBALSEQNO) " % ( self.GetNumDb(), self.GetAuthorisingDbNo() ) 
00146     return "\n".join([smry] + [ "%-10s %s " % ( self.GetStatusAsString(i), repr(con)) for i,con in enumerate(self) ])
00147 DbiCascader.__repr__ = DbiCascader__repr__
00148             
00149 def DbiCascader__check(self):
00150     for i,con in enumerate(self):
00151         n = con.numconnectedstatements
00152         assert n == 0 , ( n, i, con )
00153 DbiCascader.check = DbiCascader__check
00154 
00155 def DbiConnection__repr__(self):
00156     return  " %-20s #%d %-10s %-10s %s " % ( self.GetDbName(), self.GetNumConnectedStatements(), ("not-tmp","tmp")[self.IsTemporary()] , ("open","closed")[self.IsClosed()] , self.GetUrl() ) 
00157 DbiConnection.__repr__ = DbiConnection__repr__
00158 
00159 def DbiStatement__del__(self):
00160     print "DbiStatement__del__ committing hari-kari "
00161     self.IsA().Destructor(self)  ## hari-kari   http://wlav.web.cern.ch/wlav/pyroot/memory.html
00162 DbiStatement.__del__ = DbiStatement__del__
00163 
00164 
00165 def DbiCtx__repr__(self):
00166     """
00167     Special handling of the DbiCtx repr so that only properties 
00168     that have been set (as recorded in the "mask" property ) are shown  
00169     """
00170     getters = Wrap(DbiCtx).getters 
00171     prps = [ (g,getattr(self,'Get%s'%g)()) for g in getters if getattr( Ctx,'k%s'%g , 0) & self.mask > 0 or getattr( Ctx,'k%s'%g , 0) == 0 ] 
00172     return pprint.pformat( dict( prps ) ,indent=4)
00173 DbiCtx.__repr__ = DbiCtx__repr__
00174 
00175 def DbiCtx__call__( self, *args , **kwa ):
00176     """
00177     Shorthand context attribute setting in kwa style
00178     """
00179     for arg in args:
00180         self.Update(arg)
00181     for k,v in kwa.items():
00182         setattr( self, k, v )
00183     return self
00184 DbiCtx.__call__ = DbiCtx__call__
00185 
00186 
00187 def DybDbi__comment( self, *args , **kwa ):
00188     """ 
00189     Cheap trick to scribble on the mysql command list ... in order to see the order of things::
00190 
00191          gDbi.comment("hello","world")
00192 
00193     """
00194     dbno = kwa.pop('dbno', 0)
00195     comment = "\n".join(map(lambda l:"# %s"%l, args))
00196     log.info( comment )
00197     self.cascader[dbno].CreatePreparedStatement( comment )
00198     pass
00199 DybDbi.comment = DybDbi__comment
00200 
00201 
00202 
00203 
00204 
00205 
00206 ## Detector subclass attributes with known representations, needed as do not follow Get/Set convention ... 
00207 detector_reps = dict( 
00208    detName=lambda x:x.detName(),
00209    site=lambda x:Site.AsString(x.site()) , 
00210    detectorId=lambda x:DetectorId.AsString(x.detectorId()),  
00211    sensorId=lambda x:x.sensorId(),
00212    ring=lambda x:x.ring(),
00213    column=lambda x:x.column(),
00214    wallNumber=lambda x:x.wallNumber(),
00215    wallSpot=lambda x:x.wallSpot(),
00216    panelRow=lambda x:x.panelRow(),
00217    layer=lambda x:x.layer(),
00218    strip=lambda x:x.strip(),
00219 )
00220 DetectorSensor.__repr__ = lambda self:pprint.pformat(dict([(n,detector_reps[n](self) ) for n in dir(DetectorSensor) if n in detector_reps ]), indent=4 )    
00221 
00222 
00223 from TimeStampExt import *
00224 
00225 
00226 ## reluctant to hive-off due to gDbi
00227 from nose.tools import make_decorator
00228 from datetime import datetime
00229 
00230 
00231 from DybPython import DBConf, DBCas
00232 
00233 class Level(int):
00234     """
00235 
00236          ===============   =========================================
00237            OutputLevel 
00238          ===============   =========================================
00239           WARNING (110)      quiet enough for overview of errors 
00240           INFO (100)         normal
00241           DEBUG (50)         quite a few errors to chase
00242          ===============   =========================================
00243     """
00244     levels = dict( VERBOSE=1, DEBUG3=60, DEBUG2=70, DEBUG1=80, MONITOR=90, INFO=100, WARNING=110, ERROR=130, FATAL=140, NEVER=99999 )
00245     def From(cls, s):
00246         """Converts level names to DBI OutputLevel enum integers, or vv """
00247         if isinstance( s, basestring):
00248             val = cls.levels.get( s.upper() , None)
00249             assert val , "level %s is not recogized %s " % ( s, repr(cls.levels) )  
00250             return Level(val)            
00251         elif isinstance( s, int ):
00252             return Level(s)
00253         else:
00254             return None
00255     From = classmethod(From)
00256     def __repr__(self):
00257         return "Level %s " % ( int(self) )   
00258 
00259 def LOG(level="INFO"):
00260     """
00261     By wrapping a test function with this decorator,
00262     the logging level is changed to the chosen level 
00263     while the test is running.
00264     """
00265     level = Level.From(level)
00266     def _decorate(func):
00267         def _wrapper(*args, **kargs):
00268             gDbi.comment("entering %s " % func.__name__ , "")
00269             ol = gDbi.GetOutputLevel()
00270             gDbi.SetOutputLevel(level)
00271             func(*args, **kargs)
00272             gDbi.SetOutputLevel(ol)
00273             gDbi.comment("exiting %s " % func.__name__ , "")
00274         _wrapper = make_decorator(func)(_wrapper)
00275         return _wrapper
00276     return _decorate
00277 
00278 def MYSQLDUMP(level="INFO", opt=" --extended-insert=0 --skip-comments " , cfdir=None, reference=False ):
00279     """
00280     By wrapping a test function with this decorator,
00281     the database is mysqldumped after the test has run 
00282    
00283     The output dumps are saved in a directory created at path  
00284     based on the names of test module and function
00285     """
00286     level = Level.From(level)
00287     def _decorate(func):
00288         def _wrapper(*args, **kargs):
00289             print "MYSQLDUMP for func %s  " % ( func.__name__ )
00290             ol = gDbi.GetOutputLevel()
00291             gDbi.SetOutputLevel(level)
00292             func(*args, **kargs)
00293             gDbi.SetOutputLevel(ol)
00294             dir = os.path.join( os.getcwd(), "tests", func.__module__ , func.__name__ ) 
00295             DBCas.Dump( dir=dir, opt=opt , cfdir=cfdir, reference=reference )
00296         _wrapper = make_decorator(func)(_wrapper)
00297         return _wrapper
00298     return _decorate
00299 
00300 
00301 def POST(level="WARNING"):
00302     """
00303     By wrapping a test function with this decorator, some 
00304     post test checks are performed on the cascade
00305 
00306     Distributing usage of this throughout the a collection of 
00307     nosetests is useful when searching for which test is messing something up.  
00308     """ 
00309     level = Level.From(level)
00310     def _decorate(func):
00311         def _wrapper(*args, **kargs):
00312             print "POST for func %s  " % ( func.__name__ )
00313             ol = gDbi.outputlevel
00314             gDbi.outputlevel = level
00315             func(*args, **kargs)
00316             gDbi.cascader.check()
00317             gDbi.outputlevel = ol
00318         _wrapper = make_decorator(func)(_wrapper)
00319         return _wrapper
00320     return _decorate
00321 
00322 
00323 
00324 
00325 __all__ += "LOG MYSQLDUMP POST".split()
00326 
00327 
00328 
00329 
| Classes | Job Modules | Data Objects | Services | Algorithms | Tools | Packages | Directories | Tracs |

Generated on Mon Apr 11 20:17:17 2011 for DybDbi by doxygen 1.4.7