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  --tool=<TOOL> 
 21   Run TOOL instead of the main GUI. 
 22  --text-domain=<text domain> 
 23   Set this to change the name of the language file to be loaded. 
 24   Note, this does not change the directory the file is searched in, 
 25   only the name of the file where messages are loaded from. The 
 26   standard textdomain is, of course, "gnumed.mo". 
 27  --log-file=<file> 
 28   Use this to change the name of the log file. 
 29   See gmLog2.py to find out where the standard log file would 
 30   end up. 
 31  --conf-file=<file> 
 32   Use configuration file <file> instead of searching for it in 
 33   standard locations. 
 34  --lang-gettext=<language> 
 35   Explicitly set the language to use in gettext translation. The very 
 36   same effect can be achieved by setting the environment variable $LANG 
 37   from a launcher script. 
 38  --override-schema-check 
 39   Continue loading the client even if the database schema version 
 40   and the client software version cannot be verified to be compatible. 
 41  --skip-update-check 
 42   Skip checking for client updates. This is useful during development 
 43   and when the update check URL is unavailable (down). 
 44  --local-import 
 45   Adjust the PYTHONPATH such that GNUmed can be run from a local source tree. 
 46  --ui=<ui type> 
 47   Start an alternative UI. Defaults to wxPython if not specified. 
 48   Currently "wxp" (wxPython) only. 
 49  --wxp=<version> 
 50   Explicitely request a wxPython version. Can be set to either "2" or "3". 
 51   Defaults to "try 3, then 2" if not set. 
 52  --version, -V 
 53   Show version information. 
 54  --help, -h, or -? 
 55   Show this help. 
 56  """ 
 57  #========================================================== 
 58  __author__ = "H. Herb <hherb@gnumed.net>, K. Hilbert <Karsten.Hilbert@gmx.net>, I. Haywood <i.haywood@ugrad.unimelb.edu.au>" 
 59  __license__ = "GPL v2 or later (details at http://www.gnu.org)" 
 60   
 61   
 62  # standard library 
 63  import sys 
 64  import os 
 65  import platform 
 66  import faulthandler 
 67  import random 
 68  import logging 
 69  import signal 
 70  import os.path 
 71  import shutil 
 72  import stat 
 73  import io 
 74   
 75   
 76  # do not run as module 
 77  if __name__ != "__main__": 
 78          print("GNUmed startup: This is not intended to be imported as a module !") 
 79          print("-----------------------------------------------------------------") 
 80          print(__doc__) 
 81          sys.exit(1) 
 82   
 83   
 84  # do not run as root 
 85  if os.name in ['posix'] and os.geteuid() == 0: 
 86          print(""" 
 87  GNUmed startup: GNUmed should not be run as root. 
 88  ------------------------------------------------- 
 89   
 90  Running GNUmed as <root> can potentially put all 
 91  your medical data at risk. It is strongly advised 
 92  against. Please run GNUmed as a non-root user. 
 93  """) 
 94          sys.exit(1) 
 95   
 96  #---------------------------------------------------------- 
 97  current_client_version = '1.8.rc1' 
 98  current_client_branch = '1.8' 
 99   
100  _log = None 
101  _pre_log_buffer = [] 
102  _cfg = None 
103  _old_sig_term = None 
104  _known_short_options = 'h?V' 
105  _known_long_options = [ 
106          'debug', 
107          'slave', 
108          'skip-update-check', 
109          'profile=', 
110          'text-domain=', 
111          'log-file=', 
112          'conf-file=', 
113          'lang-gettext=', 
114          'ui=', 
115          'override-schema-check', 
116          'local-import', 
117          'help', 
118          'version', 
119          'hipaa', 
120          'wxp=', 
121          'tool=' 
122  ] 
123   
124  _known_ui_types = [ 
125          'web', 
126          'wxp', 
127          'chweb' 
128  ] 
129   
130  _known_tools = [ 
131          'check_enc_epi_xref', 
132          'export_pat_emr_structure' 
133  ] 
134   
135   
136  import_error_sermon = """ 
137  GNUmed startup: Cannot load GNUmed Python modules ! 
138  --------------------------------------------------- 
139  CRITICAL ERROR: Program halted. 
140   
141  Please make sure you have: 
142   
143   1) the required third-party Python modules installed 
144   2) the GNUmed Python modules linked or installed into site-packages/ 
145      (if you do not run from a CVS tree the installer should have taken care of that) 
146   3) your PYTHONPATH environment variable set up correctly 
147   
148  <sys.path> is currently set to: 
149   
150   %s 
151   
152  If you are running from a copy of the CVS tree make sure you 
153  did run gnumed/check-prerequisites.sh with good results. 
154   
155  If you still encounter errors after checking the above 
156  requirements please ask on the mailing list. 
157  """ 
158   
159   
160  missing_cli_config_file = """ 
161  GNUmed startup: Missing configuration file. 
162  ------------------------------------------- 
163   
164  You explicitly specified a configuration file 
165  on the command line: 
166   
167          --conf-file=%s 
168   
169  The file does not exist, however. 
170  """ 
171   
172   
173  no_config_files = """ 
174  GNUmed startup: Missing configuration files. 
175  -------------------------------------------- 
176   
177  None of the below candidate configuration 
178  files could be found: 
179   
180   %s 
181   
182  Cannot run GNUmed without any of them. 
183  """ 
184   
185  #========================================================== 
186  # convenience functions 
187  #---------------------------------------------------------- 
201   
202  #========================================================== 
203  # startup helpers 
204  #---------------------------------------------------------- 
205 -def setup_fault_handler(target=None):
206 if target is None: 207 faulthandler.enable() 208 _pre_log_buffer.append('<faulthandler> enabled, target = [console]: %s' % faulthandler) 209 return 210 _pre_log_buffer.append('<faulthandler> enabled, target = [%s]: %s' % (target, faulthandler)) 211 faulthandler.enable(file = target)
212 213 #==========================================================
214 -def setup_console_encoding():
215 print_lines = [] 216 try: 217 sys.stdout.reconfigure(errors = 'surrogateescape') 218 sys.stderr.reconfigure(errors = 'surrogateescape') 219 _pre_log_buffer.append('stdout/stderr reconfigured to use <surrogateescape> for encoding errors') 220 return 221 except AttributeError: 222 line = 'cannot reconfigure sys.stdout/stderr to use <errors="surrogateescape"> (needs Python 3.7+)' 223 _pre_log_buffer.append(line) 224 print_lines.append(line) 225 try: 226 _pre_log_buffer.append('sys.stdout/stderr default to "${PYTHONIOENCODING}=%s"' % os.environ['PYTHONIOENCODING']) 227 return 228 except KeyError: 229 lines = [ 230 '${PYTHONIOENCODING} is not set up, use <PYTHONIOENCODING=utf-8:surrogateescape> in the shell (for Python < 3.7)', 231 'console encoding errors may occur' 232 ] 233 for line in lines: 234 print_lines.append(line) 235 _pre_log_buffer.append(line) 236 for line in print_lines: 237 print('GNUmed startup:', line)
238 239 #==========================================================
240 -def setup_python_path():
241 242 if not '--local-import' in sys.argv: 243 _pre_log_buffer.append('running against systemwide install') 244 return 245 246 local_python_import_dir = os.path.dirname ( 247 os.path.abspath(os.path.join(sys.argv[0], '..')) 248 ) 249 print("Running from local source tree (%s) ..." % local_python_import_dir) 250 _pre_log_buffer.append("running from local source tree: %s" % local_python_import_dir) 251 252 # does the path exist at all, physically ? 253 # (*broken* links are reported as False) 254 link_name = os.path.join(local_python_import_dir, 'Gnumed') 255 if os.path.exists(link_name): 256 _pre_log_buffer.append('local module import dir symlink exists: %s' % link_name) 257 else: 258 real_dir = os.path.join(local_python_import_dir, 'client') 259 print('Creating local module import symlink ...') 260 print(' real dir:', real_dir) 261 print(' link:', link_name) 262 try: 263 os.symlink(real_dir, link_name) 264 except AttributeError: 265 _pre_log_buffer.append('Windows does not have os.symlink(), resorting to ctypes') 266 result = _symlink_windows(real_dir, link_name) 267 _pre_log_buffer.append('ctypes.windll.kernel32.CreateSymbolicLinkW() exit code: %s', result) 268 _pre_log_buffer.append('created local module import dir symlink: link [%s] => dir [%s]' % (link_name, real_dir)) 269 270 sys.path.insert(0, local_python_import_dir) 271 _pre_log_buffer.append('sys.path with local module import base dir prepended: %s' % sys.path)
272 273 #==========================================================
274 -def setup_local_repo_path():
275 276 local_repo_path = os.path.expanduser(os.path.join ( 277 '~', 278 '.gnumed', 279 'local_code', 280 str(current_client_branch) 281 )) 282 local_wxGladeWidgets_path = os.path.join(local_repo_path, 'Gnumed', 'wxGladeWidgets') 283 284 if not os.path.exists(local_wxGladeWidgets_path): 285 _log.debug('[%s] not found', local_wxGladeWidgets_path) 286 _log.info('local wxGlade widgets repository not available') 287 return 288 289 _log.info('local wxGlade widgets repository found:') 290 _log.info(local_wxGladeWidgets_path) 291 292 if not os.access(local_wxGladeWidgets_path, os.R_OK): 293 _log.error('invalid repo: no read access') 294 return 295 296 all_entries = os.listdir(os.path.join(local_repo_path, 'Gnumed')) 297 _log.debug('repo base contains: %s', all_entries) 298 all_entries.remove('wxGladeWidgets') 299 try: 300 all_entries.remove('__init__.py') 301 except ValueError: 302 _log.error('invalid repo: lacking __init__.py') 303 return 304 try: 305 all_entries.remove('__init__.pyc') 306 except ValueError: 307 pass 308 309 if len(all_entries) > 0: 310 _log.error('insecure repo: additional files or directories found') 311 return 312 313 # repo must be 0700 (rwx------) 314 stat_val = os.stat(local_wxGladeWidgets_path) 315 _log.debug('repo stat(): %s', stat_val) 316 perms = stat.S_IMODE(stat_val.st_mode) 317 _log.debug('repo permissions: %s (octal: %s)', perms, oct(perms)) 318 if perms != 448: # octal 0700 319 if os.name in ['nt']: 320 _log.warning('this platform does not support os.stat() permission checking') 321 else: 322 _log.error('insecure repo: permissions not 0600') 323 return 324 325 print("Activating local wxGlade widgets repository (%s) ..." % local_wxGladeWidgets_path) 326 sys.path.insert(0, local_repo_path) 327 _log.debug('sys.path with repo:') 328 _log.debug(sys.path)
329 330 #==========================================================
331 -def setup_logging():
332 try: 333 from Gnumed.pycommon import gmLog2 as _gmLog2 334 except ImportError: 335 print(import_error_sermon % '\n '.join(sys.path)) 336 sys.exit(1) 337 338 print("Log file:", _gmLog2._logfile.name) 339 setup_fault_handler(target = _gmLog2._logfile) 340 341 global gmLog2 342 gmLog2 = _gmLog2 343 344 global _log 345 _log = logging.getLogger('gm.launcher')
346 347 #==========================================================
348 -def log_startup_info():
349 global _pre_log_buffer 350 if len(_pre_log_buffer) > 0: 351 _log.info('early startup log buffer:') 352 for line in _pre_log_buffer: 353 _log.info(' ' + line) 354 del _pre_log_buffer 355 _log.info('GNUmed client version [%s] on branch [%s]', current_client_version, current_client_branch) 356 _log.info('Platform: %s', platform.uname()) 357 _log.info(('Python %s on %s (%s)' % (sys.version, sys.platform, os.name)).replace('\n', '<\\n>')) 358 try: 359 import lsb_release 360 _log.info('lsb_release: %s', lsb_release.get_distro_information()) 361 except ImportError: 362 pass 363 _log.info('threading: %s', sys.thread_info) 364 _log.info('os.getcwd(): [%s]', os.getcwd()) 365 _log.info('process environment:') 366 for key, val in os.environ.items(): 367 _log.info(' %s: %s' % (('${%s}' % key).rjust(30), val)) 368 import sysconfig 369 _log.info('sysconfig - platform [%s] python version [%s]:', sysconfig.get_platform(), sysconfig.get_python_version()) 370 paths = sysconfig.get_paths() 371 for path in paths: 372 _log.info(' %s: %s', path.rjust(30), paths[path]) 373 conf_vars = sysconfig.get_config_vars() 374 for var in conf_vars: 375 _log.info(' %s: %s', var.rjust(40), conf_vars[var])
376 377 #==========================================================
378 -def setup_console_exception_handler():
379 from Gnumed.pycommon.gmTools import handle_uncaught_exception_console 380 381 sys.excepthook = handle_uncaught_exception_console
382 383 #==========================================================
384 -def setup_cli():
385 from Gnumed.pycommon import gmCfg2 386 387 global _cfg 388 _cfg = gmCfg2.gmCfgData() 389 _cfg.add_cli ( 390 short_options = _known_short_options, 391 long_options = _known_long_options 392 ) 393 394 val = _cfg.get(option = '--debug', source_order = [('cli', 'return')]) 395 if val is None: 396 val = False 397 _cfg.set_option ( 398 option = 'debug', 399 value = val 400 ) 401 402 val = _cfg.get(option = '--slave', source_order = [('cli', 'return')]) 403 if val is None: 404 val = False 405 _cfg.set_option ( 406 option = 'slave', 407 value = val 408 ) 409 410 val = _cfg.get(option = '--skip-update-check', source_order = [('cli', 'return')]) 411 if val is None: 412 val = False 413 _cfg.set_option ( 414 option = 'skip-update-check', 415 value = val 416 ) 417 418 val = _cfg.get(option = '--hipaa', source_order = [('cli', 'return')]) 419 if val is None: 420 val = False 421 _cfg.set_option ( 422 option = 'hipaa', 423 value = val 424 ) 425 426 val = _cfg.get(option = '--local-import', source_order = [('cli', 'return')]) 427 if val is None: 428 val = False 429 _cfg.set_option ( 430 option = 'local-import', 431 value = val 432 ) 433 434 _cfg.set_option ( 435 option = 'client_version', 436 value = current_client_version 437 ) 438 439 _cfg.set_option ( 440 option = 'client_branch', 441 value = current_client_branch 442 )
443 444 #==========================================================
445 -def handle_sig_term(signum, frame):
446 _log.critical('SIGTERM (SIG%s) received, shutting down ...' % signum) 447 gmLog2.flush() 448 print('GNUmed: SIGTERM (SIG%s) received, shutting down ...' % signum) 449 if frame is not None: 450 print('%s::%s@%s' % (frame.f_code.co_filename, frame.f_code.co_name, frame.f_lineno)) 451 452 # FIXME: need to do something useful here 453 454 if _old_sig_term in [None, signal.SIG_IGN]: 455 sys.exit(1) 456 else: 457 _old_sig_term(signum, frame)
458 459 #----------------------------------------------------------
460 -def setup_signal_handlers():
461 global _old_sig_term 462 old_sig_term = signal.signal(signal.SIGTERM, handle_sig_term)
463 464 #==========================================================
465 -def setup_locale():
466 gmI18N.activate_locale() 467 468 td = _cfg.get(option = '--text-domain', source_order = [('cli', 'return')]) 469 l = _cfg.get(option = '--lang-gettext', source_order = [('cli', 'return')]) 470 gmI18N.install_domain(domain = td, language = l, prefer_local_catalog = _cfg.get(option = 'local-import'))
471 472 # # make sure we re-get the default encoding 473 # # in case it changed 474 # gmLog2.set_string_encoding() 475 476 #==========================================================
477 -def handle_help_request():
478 src = [('cli', 'return')] 479 480 help_requested = ( 481 _cfg.get(option = '--help', source_order = src) or 482 _cfg.get(option = '-h', source_order = src) or 483 _cfg.get(option = '-?', source_order = src) 484 ) 485 486 if help_requested: 487 print(_( 488 'Help requested\n' 489 '--------------' 490 )) 491 print(__doc__) 492 sys.exit(0)
493 494 #==========================================================
495 -def handle_version_request():
496 src = [('cli', 'return')] 497 498 version_requested = ( 499 _cfg.get(option = '--version', source_order = src) or 500 _cfg.get(option = '-V', source_order = src) 501 ) 502 503 if version_requested: 504 505 from Gnumed.pycommon.gmPG2 import map_client_branch2required_db_version, known_schema_hashes 506 507 print('GNUmed version information') 508 print('--------------------------') 509 print('client : %s on branch [%s]' % (current_client_version, current_client_branch)) 510 print('database : %s' % map_client_branch2required_db_version[current_client_branch]) 511 print('schema hash: %s' % known_schema_hashes[map_client_branch2required_db_version[current_client_branch]]) 512 sys.exit(0)
513 514 #==========================================================
515 -def setup_paths_and_files():
516 """Create needed paths in user home directory.""" 517 518 gnumed_DIR_README_TEXT = """GNUmed Electronic Medical Record 519 520 %s/ 521 522 This directory should only ever contain files which the 523 user will come into direct contact with while using the 524 application (say, by selecting a file from the file system, 525 as when selecting document parts from files). You can create 526 subdirectories here as you see fit for the purpose. 527 528 This directory will also serve as the default directory when 529 GNUmed asks the user to select a directory for storing a 530 file. 531 532 Any files which are NOT intended for direct user interaction 533 but must be configured to live at a known location (say, 534 inter-application data exchange files) should be put under 535 the hidden directory "%s/".""" % ( 536 os.path.expanduser(os.path.join('~', 'gnumed')), 537 os.path.expanduser(os.path.join('~', '.gnumed')) 538 ) 539 540 gmTools.mkdir(os.path.expanduser(os.path.join('~', '.gnumed', 'scripts'))) 541 gmTools.mkdir(os.path.expanduser(os.path.join('~', '.gnumed', 'spellcheck'))) 542 gmTools.mkdir(os.path.expanduser(os.path.join('~', '.gnumed', 'error_logs'))) 543 gmTools.mkdir(os.path.expanduser(os.path.join('~', 'gnumed'))) 544 545 README = io.open(os.path.expanduser(os.path.join('~', 'gnumed', '00_README')), mode = 'wt', encoding = 'utf8') 546 README.write(gnumed_DIR_README_TEXT) 547 README.close() 548 549 # wxPython not available yet 550 paths = gmTools.gmPaths(app_name = 'gnumed') 551 print("Temp dir:", paths.tmp_dir) 552 553 # ensure there's a user-level config file 554 io.open(os.path.expanduser(os.path.join('~', '.gnumed', 'gnumed.conf')), mode = 'a+t').close() 555 556 # symlink log file into temporary directory for easier debugging (everything in one place) 557 logfile_link = os.path.join(paths.tmp_dir, 'zzz-gnumed.log') 558 gmTools.mklink (gmLog2._logfile.name, logfile_link, overwrite = False)
559 560 #==========================================================
561 -def setup_date_time():
562 gmDateTime.init()
563 564 #==========================================================
565 -def setup_cfg():
566 """Detect and setup access to GNUmed config file. 567 568 Parts of this will have limited value due to 569 wxPython not yet being available. 570 """ 571 572 enc = gmI18N.get_encoding() 573 paths = gmTools.gmPaths(app_name = 'gnumed') 574 575 candidates = [ 576 # the current working dir 577 ['workbase', os.path.join(paths.working_dir, 'gnumed.conf')], 578 # /etc/gnumed/ 579 ['system', os.path.join(paths.system_config_dir, 'gnumed-client.conf')], 580 # ~/.gnumed/ 581 ['user', os.path.join(paths.user_config_dir, 'gnumed.conf')], 582 # CVS/tgz tree .../gnumed/client/ (IOW a local installation) 583 ['local', os.path.join(paths.local_base_dir, 'gnumed.conf')] 584 ] 585 # --conf-file= 586 explicit_fname = _cfg.get(option = '--conf-file', source_order = [('cli', 'return')]) 587 if explicit_fname is None: 588 candidates.append(['explicit', None]) 589 else: 590 candidates.append(['explicit', explicit_fname]) 591 592 for candidate in candidates: 593 _cfg.add_file_source ( 594 source = candidate[0], 595 file = candidate[1], 596 encoding = enc 597 ) 598 599 # --conf-file given but does not actually exist ? 600 if explicit_fname is not None: 601 if _cfg.source_files['explicit'] is None: 602 _log.error('--conf-file argument does not exist') 603 print(missing_cli_config_file % explicit_fname) 604 sys.exit(1) 605 606 # any config file found at all ? 607 found_any_file = False 608 for f in _cfg.source_files.values(): 609 if f is not None: 610 found_any_file = True 611 break 612 if not found_any_file: 613 _log.error('no config file found at all') 614 print(no_config_files % '\n '.join(candidates)) 615 sys.exit(1) 616 617 # mime type handling sources 618 fname = 'mime_type2file_extension.conf' 619 _cfg.add_file_source ( 620 source = 'user-mime', 621 file = os.path.join(paths.user_config_dir, fname), 622 encoding = enc 623 ) 624 _cfg.add_file_source ( 625 source = 'system-mime', 626 file = os.path.join(paths.system_config_dir, fname), 627 encoding = enc 628 )
629 630 #==========================================================
631 -def setup_ui_type():
632 global ui_type 633 ui_type = _cfg.get(option = '--ui', source_order = [('cli', 'return')]) 634 if ui_type in [True, False, None]: 635 ui_type = 'wxp' 636 ui_type = ui_type.strip() 637 if ui_type not in _known_ui_types: 638 _log.error('unknown UI type requested: %s', ui_type) 639 _log.debug('known UI types are: %s', str(_known_ui_types)) 640 print("GNUmed startup: Unknown UI type (%s). Defaulting to wxPython client." % ui_type) 641 ui_type = 'wxp' 642 _log.debug('UI type: %s', ui_type)
643 644 #==========================================================
645 -def setup_backend_environment():
646 647 db_version = gmPG2.map_client_branch2required_db_version[current_client_branch] 648 _log.info('client expects database version [%s]', db_version) 649 _cfg.set_option ( 650 option = 'database_version', 651 value = db_version 652 ) 653 654 # set up database connection timezone 655 timezone = _cfg.get ( 656 group = 'backend', 657 option = 'client timezone', 658 source_order = [ 659 ('explicit', 'return'), 660 ('workbase', 'return'), 661 ('local', 'return'), 662 ('user', 'return'), 663 ('system', 'return') 664 ] 665 ) 666 if timezone is not None: 667 gmPG2.set_default_client_timezone(timezone)
668 669 #==========================================================
670 -def run_gui():
671 gmHooks.run_hook_script(hook = 'startup-before-GUI') 672 673 if ui_type == 'wxp': 674 from Gnumed.wxpython import gmGuiMain 675 profile_file = _cfg.get(option = '--profile', source_order = [('cli', 'return')]) 676 if profile_file is not None: 677 _log.info('writing profiling data into %s', profile_file) 678 import profile 679 profile.run('gmGuiMain.main()', profile_file) 680 else: 681 gmGuiMain.main() 682 #elif ui_type == u'web': 683 # from Gnumed.proxiedpyjamas import gmWebGuiServer 684 # gmWebGuiServer.main() 685 #elif ui_type == u'chweb': 686 # from Gnumed.CherryPy import gmGuiWeb 687 # gmGuiWeb.main() 688 689 gmHooks.run_hook_script(hook = 'shutdown-post-GUI') 690 691 return 0
692 693 #==========================================================
694 -def run_tool():
695 tool = _cfg.get(option = '--tool', source_order = [('cli', 'return')]) 696 if tool is None: 697 # not running a tool 698 return None 699 700 if tool not in _known_tools: 701 _log.error('unknown tool requested: %s', tool) 702 print('GNUmed startup: Unknown tool [%s] requested.' % tool) 703 print('GNUmed startup: Known tools: %s' % _known_tools) 704 return -1 705 706 print('') 707 print('==============================================') 708 print('Running tool: %s' % tool) 709 print('----------------------------------------------') 710 print('') 711 712 if tool == 'check_enc_epi_xref': 713 from Gnumed.business import gmEMRStructItems 714 return gmEMRStructItems.check_fk_encounter_fk_episode_x_ref() 715 716 if tool == 'export_pat_emr_structure': 717 # setup praxis 718 from Gnumed.business import gmPraxis 719 praxis = gmPraxis.gmCurrentPraxisBranch(branch = gmPraxis.get_praxis_branches()[0]) 720 # get patient 721 from Gnumed.business import gmPersonSearch 722 pat = gmPersonSearch.ask_for_patient() 723 # setup exporters 724 from Gnumed.business import gmEMRStructItems 725 from Gnumed.exporters import gmTimelineExporter 726 from Gnumed.exporters import gmPatientExporter 727 while pat is not None: 728 print('patient:', pat['description_gender']) 729 # as EMR structure 730 fname = os.path.expanduser('~/gnumed/gm-emr_structure-%s.txt' % pat.subdir_name) 731 print('EMR structure:', gmEMRStructItems.export_emr_structure(patient = pat, filename = fname)) 732 # as timeline 733 fname = os.path.expanduser('~/gnumed/gm-emr-%s.timeline' % pat.subdir_name) 734 try: 735 print('EMR timeline:', gmTimelineExporter.create_timeline_file ( 736 patient = pat, 737 filename = fname, 738 include_documents = True, 739 include_vaccinations = True, 740 include_encounters = True 741 )) 742 finally: 743 pass 744 # as journal by encounter 745 exporter = gmPatientExporter.cEMRJournalExporter() 746 fname = os.path.expanduser('~/gnumed/gm-emr-journal_by_encounter-%s.txt' % pat.subdir_name) 747 print('EMR journal (by encounter):', exporter.save_to_file_by_encounter(patient = pat, filename = fname)) 748 # as journal by mod time 749 fname = os.path.expanduser('~/gnumed/gm-emr-journal_by_mod_time-%s.txt' % pat.subdir_name) 750 print('EMR journal (by mod time):', exporter.save_to_file_by_mod_time(patient = pat, filename = fname)) 751 # as statistical summary 752 fname = os.path.expanduser('~/gnumed/gm-emr-statistics-%s.txt' % pat.subdir_name) 753 output_file = io.open(fname, mode = 'wt', encoding = 'utf8', errors = 'replace') 754 emr = pat.emr 755 output_file.write(emr.format_statistics()) 756 output_file.close() 757 print('EMR statistics:', fname) 758 # as text file 759 exporter = gmPatientExporter.cEmrExport(patient = pat) 760 fname = os.path.expanduser('~/gnumed/gm-emr-text_export-%s.txt' % pat.subdir_name) 761 output_file = io.open(fname, mode = 'wt', encoding = 'utf8', errors = 'replace') 762 exporter.set_output_file(output_file) 763 exporter.dump_constraints() 764 exporter.dump_demographic_record(True) 765 exporter.dump_clinical_record() 766 exporter.dump_med_docs() 767 output_file.close() 768 print('EMR text file:', fname) 769 # another patient ? 770 pat = gmPersonSearch.ask_for_patient() 771 772 return 0 773 774 # tool export_patient_as (vcf, gdt, ...) 775 #if tool == 'export_pat_demographics': 776 777 # should not happen (because checked against _known_tools) 778 return -1
779 780 #========================================================== 781 # shutdown helpers 782 #----------------------------------------------------------
783 -def shutdown_backend():
784 gmPG2.shutdown()
785 786 #==========================================================
787 -def shutdown_logging():
788 789 # if _cfg.get(option = u'debug'): 790 # import types 791 792 # def get_refcounts(): 793 # refcount = {} 794 # # collect all classes 795 # for module in sys.modules.values(): 796 # for sym in dir(module): 797 # obj = getattr(module, sym) 798 # if type(obj) is types.ClassType: 799 # refcount[obj] = sys.getrefcount(obj) 800 # # sort by refcount 801 # pairs = map(lambda x: (x[1],x[0]), refcount.items()) 802 # pairs.sort() 803 # pairs.reverse() 804 # return pairs 805 806 # rcfile = io.open('./gm-refcount.lst', 'wt', encoding = 'utf8') 807 # for refcount, class_ in get_refcounts(): 808 # if not class_.__name__.startswith('wx'): 809 # rcfile.write(u'%10d %s\n' % (refcount, class_.__name__)) 810 # rcfile.close() 811 812 # do not choke on Windows 813 logging.raiseExceptions = False
814 815 #==========================================================
816 -def shutdown_tmp_dir():
817 818 tmp_dir = gmTools.gmPaths().tmp_dir 819 820 if _cfg.get(option = 'debug'): 821 _log.debug('not removing tmp dir (--debug mode): %s', tmp_dir) 822 return 823 824 _log.warning('removing tmp dir: %s', tmp_dir) 825 shutil.rmtree(tmp_dir, True)
826 827 #========================================================== 828 # main - launch the GNUmed wxPython GUI client 829 #---------------------------------------------------------- 830 831 random.seed() 832 833 # setup 834 setup_fault_handler(target = None) 835 setup_console_encoding() 836 setup_python_path() 837 setup_logging() 838 log_startup_info() 839 setup_console_exception_handler() 840 setup_cli() 841 setup_signal_handlers() 842 setup_local_repo_path() 843 844 from Gnumed.pycommon import gmI18N 845 from Gnumed.pycommon import gmTools 846 from Gnumed.pycommon import gmDateTime 847 848 setup_locale() 849 handle_help_request() 850 handle_version_request() 851 setup_paths_and_files() 852 setup_date_time() 853 setup_cfg() 854 setup_ui_type() 855 856 from Gnumed.pycommon import gmPG2 857 if ui_type in ['web']: 858 gmPG2.auto_request_login_params = False 859 setup_backend_environment() 860 861 # main 862 exit_code = run_tool() 863 if exit_code is None: 864 from Gnumed.pycommon import gmHooks 865 exit_code = run_gui() 866 867 # shutdown 868 shutdown_backend() 869 shutdown_tmp_dir() 870 _log.info('Normally shutting down as main module.') 871 shutdown_logging() 872 873 sys.exit(exit_code) 874 875 #========================================================== 876