00001 """
00002 This module provides the machinery for dressing of classes ...
00003 by adding/replacing the __repr__ methods, to get the classes to be
00004 more amenable interactively and adding a __props__ method to
00005 represent instances as simple dicts
00006
00007 http://dayabay.phys.ntu.edu.tw/tracs/env/wiki/EventIntrospection
00008
00009 Useful slides from Thomas Ruf :
00010
00011 http://lhcb-reconstruction.web.cern.ch/lhcb-reconstruction/Python/GaudiPython_and_RawData.pdf
00012 http://lhcb-reconstruction.web.cern.ch/lhcb-reconstruction/Python/Dst_as_Ntuple_files/frame.htm
00013
00014 libMathCore is loaded as a workaround for
00015 http://dayabay.phys.ntu.edu.tw/tracs/env/ticket/42
00016
00017 TODO:
00018 the default repr provides the address of the object
00019 ... this should also be given in the replacement ???
00020
00021
00022 methods to check for useful output
00023 StreamBuffer& KeyedObject<int>::serialize(StreamBuffer& s)
00024
00025 """
00026
00027 import ROOT
00028 ROOT.gSystem.Load("libMathCore")
00029 import GaudiPython as gp
00030 import PyCintex as pc
00031
00032
00033
00034
00035 def reload_():
00036 import sys
00037 reload(sys.modules[__name__])
00038
00039
00040 def docs_(kls):
00041 docs = [getattr(kls,d).__doc__ for d in dir(kls)]
00042 return docs
00043
00044
00045 def __repr__(self):
00046 """ pretty print a dict of the properties of the object
00047 if an __props__ method that returns the dict has been provided by
00048 or added to the class
00049 """
00050 if hasattr(self,"__props__"):
00051 return format_(self.__props__())
00052 else:
00053 return "<%s customized __repr__ not available due to lack of __props__ method >" % self.__class__.__name__
00054
00055 def __str__(self):
00056 """ invokes the print or fillstream methods of the object if they have them
00057 to see this with newlines honoured use "print obj" rather than "str(obj)"
00058 """
00059 s = []
00060 s.append( "<%s >" % self.__class__.__name__ )
00061 pr = print_(self)
00062 if pr:
00063 s.append( pr )
00064 fs = fillStream_(self)
00065 if fs:
00066 s.append( fs )
00067 return "\n".join(s)
00068
00069
00070 def dress_classes( klasses ):
00071 """ replace the repr str methods of the classes """
00072 for kln,prp in klasses.items():
00073 kls = pc.makeClass(kln)
00074 kls.__props__ = prp
00075 kls.__repr__ = __repr__
00076 kls.__str__ = __str__
00077
00078
00079 def undress_classes( klasses ):
00080 """ may be unneeded ...
00081 call the base repr like so
00082 object.__repr__(obj)
00083 """
00084 for kln,prp in klasses.items():
00085 kls = pc.makeClass(kln)
00086 if hasattr(kls,'__props__'):
00087 del kls.__props__
00088 if hasattr(kls,'__repr__'):
00089 del kls.__repr__
00090 if hasattr(kls,'__str__'):
00091 del kls.__str__
00092
00093
00094
00095 def hdr_(self):
00096 """ how to access the address of the object on the C++ side ?? """
00097 d = {}
00098 d.update( _class=self.__class__.__name__ )
00099 return d
00100
00101
00102
00103 class irange(object):
00104 """ cranking the iterator from py side TODO: yield a count in a tuple with the item """
00105 def __init__(self, begin, end):
00106 self.begin, self.end = begin, end
00107 self.count = 0
00108 def __iter__(self):
00109 it = self.begin
00110 while it != self.end:
00111 yield it.__deref__()
00112 it.__postinc__(1)
00113 self.count += 1
00114
00115 def print_(o):
00116 """
00117 special handling to call print methods like :
00118 void GenParticle::print(basic_ostream<char,char_traits<char> >& ostr = std::cout)
00119 as print is a reserved word in python and as the output goes to a stream
00120 """
00121 if hasattr(o,"print"):
00122 ss = gp.gbl.stringstream()
00123 __print = getattr(o, "print")
00124 __print(ss)
00125 return ss.str()
00126 return None
00127
00128
00129 def fillStream_(o):
00130 if hasattr(o,"fillStream"):
00131 ss = gp.gbl.stringstream()
00132 __fillStream = getattr(o, "fillStream")
00133 __fillStream(ss)
00134 return ss.str()
00135 return None
00136
00137
00138
00139 """
00140 this inhibits a number of GaudiPython.AppMgr.run calls (usually one)
00141 before replacing this member function
00142
00143 this allows to import a module that does g.run(n) without invoking the
00144 run allowing some further condifuration before really starting the run
00145
00146 """
00147
00148 _run_inhibit = 1
00149 _run_original = None
00150
00151 def _control_run(self,nevt):
00152 """ this prevents g.run(n) from doing so """
00153
00154 assert self.__class__.__name__ == 'AppMgr'
00155 global _run_inhibit
00156 global _run_original
00157
00158 assert not self.__class__.run == _run_original , "this should never be invoked after the inhibit is lifted "
00159
00160 if _run_inhibit > 0:
00161 print "_control_run inhibiting run %s nevt %s _run_inhibit %s " % ( self, nevt, _run_inhibit )
00162 _run_inhibit -= 1
00163 else:
00164 self.__class__.run = _run_original
00165 print "_control_run replace original run %s nevt %s _run_inhibit %s " % ( self, nevt, _run_inhibit )
00166 self.run(nevt)
00167
00168 def inhibit_run(n=1):
00169
00170 from GaudiPython import AppMgr
00171 global _run_original
00172 _run_original = AppMgr.run
00173 AppMgr.run = _control_run
00174
00175 global _run_inhibit
00176 _run_inhibit = n
00177
00178
00179 def format_(o):
00180 import pprint
00181 return pprint.pformat(o)
00182
00183
00184 class PrintLogger:
00185 def hdr(self):
00186 return "<%s [0x%08X] > " % ( self.__class__.__name__ , id(self) )
00187 def log(self, *args , **kwargs ):
00188 import pprint
00189 print "%s %s %s" % ( self.hdr() , " ".join(args), pprint.pformat(kwargs) )
00190
00191
00192
00193
00194
00195
00196