1 """GNUmed hooks framework.
2
3 This module provides convenience functions and definitions
4 for accessing the GNUmed hooks framework.
5
6 This framework calls the script
7
8 ~/.gnumed/scripts/hook_script.py
9
10 at various times during client execution. The script must
11 contain a function
12
13 def run_script(hook=None):
14 pass
15
16 which accepts a single argument <hook>. That argument will
17 contain the hook that is being activated.
18
19 This source code is protected by the GPL licensing scheme.
20 Details regarding the GPL are available at http://www.gnu.org
21 You may use and share it as long as you don't deny this right
22 to anybody else.
23 """
24
25 __version__ = "$Revision: 1.18 $"
26 __author__ = "K. Hilbert <Karsten.Hilbert@gmx.net>"
27 __license__ = "GPL (details at http://www.gnu.org)"
28
29
30
31 import os, sys, stat, logging
32
33 _log = logging.getLogger('gm.hook')
34 _log.info(__version__)
35
36
37
38 if __name__ == '__main__':
39 sys.path.insert(0, '../../')
40 from Gnumed.pycommon import gmDispatcher, gmTools
41
42
43 known_hooks = [
44 u'post_patient_activation',
45
46 u'shutdown-post-GUI',
47 u'startup-after-GUI-init',
48 u'startup-before-GUI',
49
50 u'request_user_attention',
51 u'app_activated_startup',
52 u'app_activated',
53 u'app_deactivated',
54
55 u'after_substance_intake_modified',
56 u'after_test_result_modified',
57 u'after_soap_modified',
58
59 u'after_new_doc_created',
60 u'before_print_doc',
61 u'before_fax_doc',
62 u'before_mail_doc',
63 u'before_print_doc_part',
64 u'before_fax_doc_part',
65 u'before_mail_doc_part',
66 u'before_external_doc_access',
67
68 u'db_maintenance_warning'
69 ]
70
71 _log.debug('known hooks:')
72 for hook in known_hooks:
73 _log.debug(hook)
74
75
76 hook_module = None
77
79
80 global hook_module
81 if not reimport:
82 if hook_module is not None:
83 return True
84
85
86
87
88 script_name = 'hook_script.py'
89 script_path = os.path.expanduser(os.path.join('~', '.gnumed', 'scripts'))
90 full_script = os.path.join(script_path, script_name)
91
92 if not os.access(full_script, os.F_OK):
93 _log.warning('creating default hook script')
94 f = open(full_script, 'w')
95 f.write("""
96 # known hooks:
97 # %s
98
99 def run_script(hook=None):
100 pass
101 """ % '# '.join(known_hooks))
102 f.close()
103 os.chmod(full_script, 384)
104
105 if os.path.islink(full_script):
106 gmDispatcher.send (
107 signal = 'statustext',
108 msg = _('Script must not be a link: [%s].') % full_script
109 )
110 return False
111
112 if not os.access(full_script, os.R_OK):
113 gmDispatcher.send (
114 signal = 'statustext',
115 msg = _('Script must be readable by the calling user: [%s].') % full_script
116 )
117 return False
118
119 script_mode = stat.S_IMODE(os.stat(full_script).st_mode)
120 if script_mode != 384:
121 gmDispatcher.send (
122 signal = 'statustext',
123 msg = _('Script must be readable by the calling user only (permissions "0600"): [%s].') % full_script
124 )
125 return False
126
127 try:
128 tmp = gmTools.import_module_from_directory(script_path, script_name)
129 except StandardError:
130 _log.exception('cannot import hook script')
131 return False
132
133 hook_module = tmp
134
135
136
137 _log.info('hook script: %s', full_script)
138 return True
139
141
142
143 if hook not in known_hooks:
144 raise ValueError('run_hook_script(): unknown hook [%s]' % hook)
145
146 if not import_hook_module(reimport = False):
147 return False
148
149 try:
150 hook_module.run_script(hook = hook)
151 except StandardError:
152 _log.exception('error running hook script for [%s]', hook)
153 gmDispatcher.send (
154 signal = u'statustext',
155 msg = _('Error running hook [%s] script.') % hook,
156 beep = True
157 )
158 return False
159
160 return True
161
162 if __name__ == '__main__':
163
164 run_hook_script(hook = 'shutdown-post-GUI')
165 run_hook_script(hook = 'invalid hook')
166
167
168