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