Package Gnumed :: Module gnumed
[frames] | no frames]

Source Code for Module Gnumed.gnumed

  1  #!/usr/bin/env python 
  2   
  3  __doc__ = """GNUmed client launcher. 
  4   
  5  This is the launcher for the GNUmed GUI client. It takes 
  6  care of all the pre- and post-GUI runtime environment setup. 
  7   
  8  --quiet 
  9   Be extra quiet and show only _real_ errors in the log. 
 10  --debug 
 11   Pre-set the [debug mode] checkbox in the login dialog to 
 12   increase verbosity in the log file. Useful for, well, debugging :-) 
 13  --slave 
 14   Pre-set the [enable remote control] checkbox in the login 
 15   dialog to enable the XML-RPC remote control feature. 
 16  --hipaa 
 17   Enable HIPAA functionality which has user impact. 
 18  --profile=<file> 
 19   Activate profiling and write profile data to <file>. 
 20  --text-domain=<text domain> 
 21   Set this to change the name of the language file to be loaded. 
 22   Note, this does not change the directory the file is searched in, 
 23   only the name of the file where messages are loaded from. The 
 24   standard textdomain is, of course, "gnumed.mo". 
 25  --log-file=<file> 
 26   Use this to change the name of the log file. 
 27   See gmLog2.py to find out where the standard log file would 
 28   end up. 
 29  --conf-file=<file> 
 30   Use configuration file <file> instead of searching for it in 
 31   standard locations. 
 32  --lang-gettext=<language> 
 33   Explicitly set the language to use in gettext translation. The very 
 34   same effect can be achieved by setting the environment variable $LANG 
 35   from a launcher script. 
 36  --override-schema-check 
 37   Continue loading the client even if the database schema version 
 38   and the client software version cannot be verified to be compatible. 
 39  --skip-update-check 
 40   Skip checking for client updates. This is useful during development 
 41   and when the update check URL is unavailable (down). 
 42  --local-import 
 43   Adjust the PYTHONPATH such that GNUmed can be run from a local source tree. 
 44  --ui=<ui type> 
 45   Start an alternative UI. Defaults to wxPython if not specified. 
 46   Valid values: web (CherryPy), wxp (wxPython) 
 47  --version, -V 
 48   Show version information. 
 49  --help, -h, or -? 
 50   Show this help. 
 51  """ 
 52  #========================================================== 
 53  __version__ = "$Revision: 1.169 $" 
 54  __author__  = "H. Herb <hherb@gnumed.net>, K. Hilbert <Karsten.Hilbert@gmx.net>, I. Haywood <i.haywood@ugrad.unimelb.edu.au>" 
 55  __license__ = "GPL (details at http://www.gnu.org)" 
 56   
 57  # standard library 
 58  import sys, os, os.path, signal, logging, platform 
 59   
 60   
 61  # do not run as module 
 62  if __name__ != "__main__": 
 63          print "GNUmed startup: This is not intended to be imported as a module !" 
 64          print "-----------------------------------------------------------------" 
 65          print __doc__ 
 66          sys.exit(1) 
 67   
 68   
 69  # do not run as root 
 70  if os.name in ['posix'] and os.geteuid() == 0: 
 71          print """ 
 72  GNUmed startup: GNUmed should not be run as root. 
 73  ------------------------------------------------- 
 74   
 75  Running GNUmed as <root> can potentially put all 
 76  your medical data at risk. It is strongly advised 
 77  against. Please run GNUmed as a non-root user. 
 78  """ 
 79          sys.exit(1) 
 80   
 81  #---------------------------------------------------------- 
 82  #current_client_version = u'0.7.rc1' 
 83  current_client_version = u'GIT HEAD' 
 84  #current_client_branch = u'0.7' 
 85  current_client_branch = u'GIT tree' 
 86   
 87  _log = None 
 88  _cfg = None 
 89  _old_sig_term = None 
 90  _known_short_options = u'h?V' 
 91  _known_long_options = [ 
 92          u'debug', 
 93          u'slave', 
 94          u'skip-update-check', 
 95          u'profile=', 
 96          u'text-domain=', 
 97          u'log-file=', 
 98          u'conf-file=', 
 99          u'lang-gettext=', 
100          u'ui=', 
101          u'override-schema-check', 
102          u'local-import', 
103          u'help', 
104          u'version', 
105          u'hipaa' 
106  ] 
107   
108  _known_ui_types = [ 
109          u'web', 
110          u'wxp' 
111  ] 
112   
113  import_error_sermon = """ 
114  GNUmed startup: Cannot load GNUmed Python modules ! 
115  --------------------------------------------------- 
116  CRITICAL ERROR: Program halted. 
117   
118  Please make sure you have: 
119   
120   1) the required third-party Python modules installed 
121   2) the GNUmed Python modules linked or installed into site-packages/ 
122      (if you do not run from a CVS tree the installer should have taken care of that) 
123   3) your PYTHONPATH environment variable set up correctly 
124   
125  sys.path is currently set to: 
126   
127   %s 
128   
129  If you are running from a copy of the CVS tree make sure you 
130  did run gnumed/check-prerequisites.sh with good results. 
131   
132  If you still encounter errors after checking the above 
133  requirements please ask on the mailing list. 
134  """ 
135   
136   
137  missing_cli_config_file = u""" 
138  GNUmed startup: Missing configuration file. 
139  ------------------------------------------- 
140   
141  You explicitly specified a configuration file 
142  on the command line: 
143   
144          --conf-file=%s 
145   
146  The file does not exist, however. 
147  """ 
148   
149   
150  no_config_files = u""" 
151  GNUmed startup: Missing configuration files. 
152  -------------------------------------------- 
153   
154  None of the below candidate configuration 
155  files could be found: 
156   
157   %s 
158   
159  Cannot run GNUmed without any of them. 
160  """ 
161  #========================================================== 
162  # convenience functions 
163  #========================================================== 
164 -def setup_python_path():
165 166 if not u'--local-import' in sys.argv: 167 return 168 169 print "GNUmed startup: Running from local source tree." 170 print "-----------------------------------------------" 171 172 local_python_base_dir = os.path.dirname ( 173 os.path.abspath(os.path.join(sys.argv[0], '..')) 174 ) 175 176 # does the path exist at all, physically ? 177 # (*broken* links are reported as False) 178 link_name = os.path.join(local_python_base_dir, 'Gnumed') 179 if not os.path.exists(link_name): 180 real_dir = os.path.join(local_python_base_dir, 'client') 181 print "Creating module import symlink ..." 182 print ' real dir:', real_dir 183 print ' link:', link_name 184 os.symlink(real_dir, link_name) 185 186 print "Adjusting PYTHONPATH ..." 187 sys.path.insert(0, local_python_base_dir)
188 #==========================================================
189 -def setup_logging():
190 try: 191 from Gnumed.pycommon import gmLog2 as _gmLog2 192 except ImportError: 193 sys.exit(import_error_sermon % '\n '.join(sys.path)) 194 195 global gmLog2 196 gmLog2 = _gmLog2 197 198 global _log 199 _log = logging.getLogger('gm.launcher')
200 #==========================================================
201 -def log_startup_info():
202 _log.info('Starting up as main module (%s).', __version__) 203 _log.info('GNUmed client version [%s] on branch [%s]', current_client_version, current_client_branch) 204 _log.info('Platform: %s', platform.uname()) 205 _log.info('Python %s on %s (%s)', sys.version, sys.platform, os.name) 206 try: 207 import lsb_release 208 _log.info('%s' % lsb_release.get_distro_information()) 209 except ImportError: 210 pass
211 #==========================================================
212 -def setup_console_exception_handler():
213 from Gnumed.pycommon.gmTools import handle_uncaught_exception_console 214 215 sys.excepthook = handle_uncaught_exception_console
216 #==========================================================
217 -def setup_cli():
218 from Gnumed.pycommon import gmCfg2 219 220 global _cfg 221 _cfg = gmCfg2.gmCfgData() 222 _cfg.add_cli ( 223 short_options = _known_short_options, 224 long_options = _known_long_options 225 ) 226 227 val = _cfg.get(option = '--debug', source_order = [('cli', 'return')]) 228 if val is None: 229 val = False 230 _cfg.set_option ( 231 option = u'debug', 232 value = val 233 ) 234 235 val = _cfg.get(option = '--slave', source_order = [('cli', 'return')]) 236 if val is None: 237 val = False 238 _cfg.set_option ( 239 option = u'slave', 240 value = val 241 ) 242 243 val = _cfg.get(option = '--skip-update-check', source_order = [('cli', 'return')]) 244 if val is None: 245 val = False 246 _cfg.set_option ( 247 option = u'skip-update-check', 248 value = val 249 ) 250 251 val = _cfg.get(option = '--hipaa', source_order = [('cli', 'return')]) 252 if val is None: 253 val = False 254 _cfg.set_option ( 255 option = u'hipaa', 256 value = val 257 ) 258 259 val = _cfg.get(option = '--local-import', source_order = [('cli', 'return')]) 260 if val is None: 261 val = False 262 _cfg.set_option ( 263 option = u'local-import', 264 value = val 265 ) 266 267 _cfg.set_option ( 268 option = u'client_version', 269 value = current_client_version 270 ) 271 272 _cfg.set_option ( 273 option = u'client_branch', 274 value = current_client_branch 275 )
276 277 #==========================================================
278 -def handle_sig_term(signum, frame):
279 _log.critical('SIGTERM (SIG%s) received, shutting down ...' % signum) 280 gmLog2.flush() 281 print 'GNUmed: SIGTERM (SIG%s) received, shutting down ...' % signum 282 if frame is not None: 283 print '%s::%s@%s' % (frame.f_code.co_filename, frame.f_code.co_name, frame.f_lineno) 284 285 # FIXME: need to do something useful here 286 287 if _old_sig_term in [None, signal.SIG_IGN]: 288 sys.exit(signal.SIGTERM) 289 else: 290 _old_sig_term(signum, frame)
291 #----------------------------------------------------------
292 -def setup_signal_handlers():
293 global _old_sig_term 294 old_sig_term = signal.signal(signal.SIGTERM, handle_sig_term)
295 #==========================================================
296 -def setup_locale():
297 gmI18N.activate_locale() 298 299 td = _cfg.get(option = '--text-domain', source_order = [('cli', 'return')]) 300 l = _cfg.get(option = '--lang-gettext', source_order = [('cli', 'return')]) 301 gmI18N.install_domain(domain = td, language = l, prefer_local_catalog = _cfg.get(option = u'local-import')) 302 303 # make sure we re-get the default encoding 304 # in case it changed 305 gmLog2.set_string_encoding()
306 #==========================================================
307 -def handle_help_request():
308 src = [(u'cli', u'return')] 309 310 help_requested = ( 311 _cfg.get(option = u'--help', source_order = src) or 312 _cfg.get(option = u'-h', source_order = src) or 313 _cfg.get(option = u'-?', source_order = src) 314 ) 315 316 if help_requested: 317 print _( 318 'Help requested\n' 319 '--------------' 320 ) 321 print __doc__ 322 sys.exit(0)
323 #==========================================================
324 -def handle_version_request():
325 src = [(u'cli', u'return')] 326 327 version_requested = ( 328 _cfg.get(option = u'--version', source_order = src) or 329 _cfg.get(option = u'-V', source_order = src) 330 ) 331 332 if version_requested: 333 334 from Gnumed.pycommon.gmPG2 import map_client_branch2required_db_version, known_schema_hashes 335 336 print 'GNUmed version information' 337 print '--------------------------' 338 print 'client : %s on branch [%s]' % (current_client_version, current_client_branch) 339 print 'database : %s' % map_client_branch2required_db_version[current_client_branch] 340 print 'schema hash: %s' % known_schema_hashes[map_client_branch2required_db_version[current_client_branch]] 341 sys.exit(0)
342 343 #==========================================================
344 -def setup_paths_and_files():
345 """Create needed paths in user home directory.""" 346 347 gmTools.mkdir(os.path.expanduser(os.path.join('~', '.gnumed', 'scripts'))) 348 gmTools.mkdir(os.path.expanduser(os.path.join('~', '.gnumed', 'spellcheck'))) 349 gmTools.mkdir(os.path.expanduser(os.path.join('~', '.gnumed', 'tmp'))) 350 gmTools.mkdir(os.path.expanduser(os.path.join('~', 'gnumed', 'export', 'docs'))) 351 gmTools.mkdir(os.path.expanduser(os.path.join('~', 'gnumed', 'export', 'xDT'))) 352 gmTools.mkdir(os.path.expanduser(os.path.join('~', 'gnumed', 'export', 'EMR'))) 353 gmTools.mkdir(os.path.expanduser(os.path.join('~', 'gnumed', 'xDT'))) 354 gmTools.mkdir(os.path.expanduser(os.path.join('~', 'gnumed', 'logs'))) 355 356 paths = gmTools.gmPaths(app_name = u'gnumed') 357 358 open(os.path.expanduser(os.path.join('~', '.gnumed', 'gnumed.conf')), 'a+').close()
359 #==========================================================
360 -def setup_date_time():
361 gmDateTime.init()
362 #==========================================================
363 -def setup_cfg():
364 """Detect and setup access to GNUmed config file. 365 366 Parts of this will have limited value due to 367 wxPython not yet being available. 368 """ 369 370 enc = gmI18N.get_encoding() 371 paths = gmTools.gmPaths(app_name = u'gnumed') 372 373 candidates = [ 374 # the current working dir 375 [u'workbase', os.path.join(paths.working_dir, 'gnumed.conf')], 376 # /etc/gnumed/ 377 [u'system', os.path.join(paths.system_config_dir, 'gnumed-client.conf')], 378 # ~/.gnumed/ 379 [u'user', os.path.join(paths.user_config_dir, 'gnumed.conf')], 380 # CVS/tgz tree .../gnumed/client/ (IOW a local installation) 381 [u'local', os.path.join(paths.local_base_dir, 'gnumed.conf')] 382 ] 383 # --conf-file= 384 explicit_fname = _cfg.get(option = u'--conf-file', source_order = [(u'cli', u'return')]) 385 if explicit_fname is None: 386 candidates.append([u'explicit', None]) 387 else: 388 candidates.append([u'explicit', explicit_fname]) 389 390 for candidate in candidates: 391 _cfg.add_file_source ( 392 source = candidate[0], 393 file = candidate[1], 394 encoding = enc 395 ) 396 397 # --conf-file given but does not actually exist ? 398 if explicit_fname is not None: 399 if _cfg.source_files['explicit'] is None: 400 _log.error('--conf-file argument does not exist') 401 sys.exit(missing_cli_config_file % explicit_fname) 402 403 # any config file found at all ? 404 found_any_file = False 405 for f in _cfg.source_files.values(): 406 if f is not None: 407 found_any_file = True 408 break 409 if not found_any_file: 410 _log.error('no config file found at all') 411 sys.exit(no_config_files % '\n '.join(candidates)) 412 413 # mime type handling sources 414 fname = u'mime_type2file_extension.conf' 415 _cfg.add_file_source ( 416 source = u'user-mime', 417 file = os.path.join(paths.user_config_dir, fname), 418 encoding = enc 419 ) 420 _cfg.add_file_source ( 421 source = u'system-mime', 422 file = os.path.join(paths.system_config_dir, fname), 423 encoding = enc 424 )
425 #==========================================================
426 -def setup_ui_type():
427 global ui_type 428 429 ui_type = _cfg.get(option = u'--ui', source_order = [(u'cli', u'return')]) 430 431 if ui_type in [True, False, None]: 432 ui_type = 'wxp' 433 434 ui_type = ui_type.strip() 435 436 if ui_type not in _known_ui_types: 437 _log.error('unknown UI type: %s', ui_type) 438 _log.debug('known UI types: %s', str(_known_ui_types)) 439 print "GNUmed startup: Unknown UI type (%s). Defaulting to wxPython client." % ui_type 440 ui_type = 'wxp' 441 442 _log.debug('UI type: %s', ui_type)
443 #==========================================================
444 -def setup_backend():
445 _log.info('client expects database version [%s]', gmPG2.map_client_branch2required_db_version[current_client_branch]) 446 447 # set up database connection timezone 448 timezone = _cfg.get ( 449 group = u'backend', 450 option = 'client timezone', 451 source_order = [ 452 ('explicit', 'return'), 453 ('workbase', 'return'), 454 ('local', 'return'), 455 ('user', 'return'), 456 ('system', 'return') 457 ] 458 ) 459 if timezone is not None: 460 gmPG2.set_default_client_timezone(timezone)
461 #==========================================================
462 -def shutdown_backend():
463 gmPG2.shutdown()
464 #==========================================================
465 -def shutdown_logging():
466 467 # if _cfg.get(option = u'debug'): 468 # import types 469 470 # def get_refcounts(): 471 # refcount = {} 472 # # collect all classes 473 # for module in sys.modules.values(): 474 # for sym in dir(module): 475 # obj = getattr(module, sym) 476 # if type(obj) is types.ClassType: 477 # refcount[obj] = sys.getrefcount(obj) 478 # # sort by refcount 479 # pairs = map(lambda x: (x[1],x[0]), refcount.items()) 480 # pairs.sort() 481 # pairs.reverse() 482 # return pairs 483 484 # rcfile = open('./gm-refcount.lst', 'wb') 485 # for refcount, class_ in get_refcounts(): 486 # if not class_.__name__.startswith('wx'): 487 # rcfile.write('%10d %s\n' % (refcount, class_.__name__)) 488 # rcfile.close() 489 490 # do not choke on Windows 491 logging.raiseExceptions = False
492 493 #========================================================== 494 # main - launch the GNUmed wxPython GUI client 495 #---------------------------------------------------------- 496 setup_python_path() 497 setup_logging() 498 log_startup_info() 499 setup_console_exception_handler() 500 setup_cli() 501 setup_signal_handlers() 502 503 from Gnumed.pycommon import gmI18N, gmTools, gmDateTime, gmHooks 504 setup_locale() 505 handle_help_request() 506 handle_version_request() 507 setup_paths_and_files() 508 setup_date_time() 509 setup_cfg() 510 setup_ui_type() 511 512 from Gnumed.pycommon import gmPG2 513 setup_backend() 514 515 516 gmHooks.run_hook_script(hook = u'startup-before-GUI') 517 518 if ui_type == u'wxp': 519 from Gnumed.wxpython import gmGuiMain 520 profile_file = _cfg.get(option = u'--profile', source_order = [(u'cli', u'return')]) 521 if profile_file is not None: 522 _log.info('writing profiling data into %s', profile_file) 523 import profile 524 profile.run('gmGuiMain.main()', profile_file) 525 else: 526 gmGuiMain.main() 527 elif ui_type == u'web': 528 from Gnumed.CherryPy import gmGuiWeb 529 gmGuiWeb.main() 530 531 gmHooks.run_hook_script(hook = u'shutdown-post-GUI') 532 533 534 shutdown_backend() 535 _log.info('Normally shutting down as main module.') 536 shutdown_logging() 537 538 #========================================================== 539