Package flumotion :: Package common :: Module boot
[hide private]

Source Code for Module flumotion.common.boot

  1  # -*- Mode: Python -*- 
  2  # vi:si:et:sw=4:sts=4:ts=4 
  3  # 
  4  # Flumotion - a streaming media server 
  5  # Copyright (C) 2004,2005,2006,2007 Fluendo, S.L. (www.fluendo.com). 
  6  # All rights reserved. 
  7   
  8  # This file may be distributed and/or modified under the terms of 
  9  # the GNU General Public License version 2 as published by 
 10  # the Free Software Foundation. 
 11  # This file is distributed without any warranty; without even the implied 
 12  # warranty of merchantability or fitness for a particular purpose. 
 13  # See "LICENSE.GPL" in the source distribution for more information. 
 14   
 15  # Licensees having purchased or holding a valid Flumotion Advanced 
 16  # Streaming Server license may use this file in accordance with the 
 17  # Flumotion Advanced Streaming Server Commercial License Agreement. 
 18  # See "LICENSE.Flumotion" in the source distribution for more information. 
 19   
 20  # Headers in this file shall remain intact. 
 21   
 22  """boostrapping functions for flumotion""" 
 23   
 24  import os 
 25  import sys 
 26   
 27  from flumotion.common.log import safeprintf 
 28   
 29  __version__ = "$Rev: 7980 $" 
 30  # Keep in sync with configure.ac 
 31  PYGTK_REQ = (2, 8, 4) 
 32  KIWI_REQ = (1, 9, 13) 
 33  GST_REQ = {'0.10': {'gstreamer': (0, 10, 0, 1), 
 34                      'gst-python': (0, 10, 0, 1)}} 
 35  USE_GOPTION_PARSER = False 
 36  USE_GTK = False 
 37  USE_GST = True 
 38   
 39   
40 -def init_gobject():
41 """ 42 Initialize pygobject. A missing or too-old pygobject will cause a 43 SystemExit exception to be raised. 44 """ 45 try: 46 import pygtk 47 pygtk.require('2.0') 48 49 import gobject 50 except ImportError: 51 raise SystemExit('ERROR: PyGTK could not be found') 52 53 if gobject.pygtk_version < PYGTK_REQ: 54 raise SystemExit('ERROR: PyGTK %s or higher is required' 55 % '.'.join(map(str, PYGTK_REQ))) 56 57 gobject.threads_init()
58 59
60 -def _init_gst_version(gst_majorminor):
61 62 def tup2version(tup): 63 return '.'.join(map(str, tup))
64 65 if gst_majorminor not in GST_REQ: 66 raise SystemExit('ERROR: Invalid FLU_GST_VERSION: %r (expected ' 67 'one of %r)' % (gst_majorminor, GST_REQ.keys())) 68 69 pygst_req = GST_REQ[gst_majorminor]['gst-python'] 70 gst_req = GST_REQ[gst_majorminor]['gstreamer'] 71 72 try: 73 import pygst 74 pygst.require(gst_majorminor) 75 import gst 76 except ImportError: 77 return False 78 except AssertionError: 79 return False 80 81 try: 82 gst_version = gst.get_gst_version() 83 pygst_version = gst.get_pygst_version() 84 except AttributeError: 85 # get_foo_version() added in 0.10.4, fall back 86 gst_version = gst.gst_version 87 pygst_version = gst.pygst_version 88 89 if gst_req[:2] != gst_version[:2]: 90 raise SystemExit( 91 'ERROR: Expected GStreamer %s, but got incompatible %s' 92 % (gst_majorminor, tup2version(gst_version[:2]))) 93 94 if gst_version < gst_req: 95 raise SystemExit( 96 'ERROR: GStreamer %s too old; install %s or newer' 97 % (tup2version(gst_version), tup2version(gst_req))) 98 99 if pygst_version < pygst_req: 100 raise SystemExit( 101 'ERROR: gst-python %s too old; install %s or newer' 102 % (tup2version(pygst_version), tup2version(pygst_req))) 103 104 return True 105 106
107 -def init_gst():
108 """ 109 Initialize pygst. A missing or too-old pygst will cause a 110 SystemExit exception to be raised. 111 """ 112 assert 'gobject' in sys.modules, "Run init_gobject() first" 113 114 gst_majorminor = os.getenv('FLU_GST_VERSION') 115 116 if gst_majorminor: 117 if not _init_gst_version(gst_majorminor): 118 raise SystemExit('ERROR: requested GStreamer version %s ' 119 'not available' % gst_majorminor) 120 else: 121 majorminors = GST_REQ.keys() 122 majorminors.sort() 123 while majorminors: 124 majorminor = majorminors.pop() 125 if _init_gst_version(majorminor): 126 gst_majorminor = majorminor 127 break 128 if not gst_majorminor: 129 raise SystemExit('ERROR: no GStreamer available ' 130 '(looking for versions %r)' % (GST_REQ.keys(), )) 131 132 return gst_majorminor
133 134
135 -def init_kiwi():
136 try: 137 from kiwi.__version__ import version as kiwi_version 138 except ImportError: 139 return False 140 141 if kiwi_version < KIWI_REQ: 142 raise SystemExit('ERROR: Kiwi %s or higher is required' 143 % '.'.join(map(str, KIWI_REQ))) 144 145 return True
146 147
148 -def init_option_parser(gtk, gst):
149 # We should only use the GOption parser if we are already going to 150 # import gobject, and if we can find a recent enough version of 151 # pygobject on our system. There were bugs in the GOption parsing 152 # until pygobject 2.15.0, so just revert to optparse if our 153 # pygobject is too old. 154 global USE_GOPTION_PARSER 155 if not gtk and not gst: 156 USE_GOPTION_PARSER = False 157 else: 158 import gobject 159 if getattr(gobject, 'pygobject_version', ()) >= (2, 15, 0): 160 USE_GOPTION_PARSER = True 161 else: 162 USE_GOPTION_PARSER = False
163 164
165 -def wrap_for_statprof(main, output_file):
166 try: 167 import statprof 168 except ImportError, e: 169 print "Profiling requested, but statprof not available (%s)" % e 170 return main 171 172 def wrapped(*args, **kwargs): 173 statprof.start() 174 try: 175 return main(*args, **kwargs) 176 finally: 177 statprof.stop() 178 statprof.display(OUT=file(output_file, 'wb'))
179 return wrapped 180 181
182 -def wrap_for_builtin_profiler(main, output_file):
183 try: 184 import cProfile as profile 185 except ImportError: 186 import profile 187 188 def wrapped(*args, **kwargs): 189 prof = profile.Profile() 190 try: 191 return prof.runcall(main, *args, **kwargs) 192 finally: 193 prof.dump_stats(output_file)
194 return wrapped 195 196
197 -def wrap_for_profiling(main):
198 199 def generate_output_file(): 200 import tempfile 201 return os.path.join(tempfile.gettempdir(), 202 'flustat.%s.%s.%d' % 203 (main.__module__, main.__name__, os.getpid()))
204 205 if os.getenv('FLU_PROFILE'): 206 return wrap_for_statprof(main, generate_output_file()) 207 elif os.getenv('FLU_BUILTIN_PROFILE'): 208 return wrap_for_builtin_profiler(main, generate_output_file()) 209 else: 210 return main 211 212
213 -def boot(path, gtk=False, gst=True, installReactor=True):
214 # python 2.5 and twisted < 2.5 don't work together 215 pythonMM = sys.version_info[0:2] 216 from twisted.copyright import version 217 twistedMM = tuple([int(n) for n in version.split('.')[0:2]]) 218 if pythonMM >= (2, 5) and twistedMM < (2, 5): 219 raise SystemError( 220 "Twisted versions older than 2.5.0 do not work with " 221 "Python 2.5 and newer. " 222 "Please upgrade Twisted or downgrade Python.") 223 224 if gtk or gst: 225 init_gobject() 226 227 if gst: 228 from flumotion.configure import configure 229 configure.gst_version = init_gst() 230 231 global USE_GTK, USE_GST 232 USE_GTK=gtk 233 USE_GST=gst 234 init_option_parser(gtk, gst) 235 236 # installing the reactor could override our packager's import hooks ... 237 if installReactor: 238 from twisted.internet import gtk2reactor 239 gtk2reactor.install(useGtk=gtk) 240 from twisted.internet import reactor 241 242 # ... so we install them again here to be safe 243 from flumotion.common import package 244 package.getPackager().install() 245 246 # this monkeypatched var exists to let reconnecting factories know 247 # when they should warn about a connection being closed, and when 248 # they shouldn't because the system is shutting down. 249 # 250 # there is no race condition here -- the reactor doesn't handle 251 # signals until it is run(). 252 reactor.killed = False 253 254 def setkilled(killed): 255 reactor.killed = killed
256 257 reactor.addSystemEventTrigger('before', 'startup', setkilled, False) 258 reactor.addSystemEventTrigger('before', 'shutdown', setkilled, True) 259 260 from flumotion.twisted import reflect 261 from flumotion.common import errors 262 from flumotion.common import setup 263 264 setup.setup() 265 266 from flumotion.common import log 267 log.logTwisted() 268 269 main = reflect.namedAny(path) 270 271 wrapped = wrap_for_profiling(main) 272 wrapped.__name__ = main.__name__ 273 274 try: 275 sys.exit(wrapped(sys.argv)) 276 except (errors.FatalError, SystemError), e: 277 safeprintf(sys.stderr, 'ERROR: %s\n', e) 278 sys.exit(1) 279