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 u'post_person_creation',
46
47 u'shutdown-post-GUI',
48 u'startup-after-GUI-init',
49 u'startup-before-GUI',
50
51 u'request_user_attention',
52 u'app_activated_startup',
53 u'app_activated',
54 u'app_deactivated',
55
56 u'after_substance_intake_modified',
57 u'after_test_result_modified',
58 u'after_soap_modified',
59
60 u'after_new_doc_created',
61 u'before_print_doc',
62 u'before_fax_doc',
63 u'before_mail_doc',
64 u'before_print_doc_part',
65 u'before_fax_doc_part',
66 u'before_mail_doc_part',
67 u'before_external_doc_access',
68
69 u'db_maintenance_warning'
70 ]
71
72 _log.debug('known hooks:')
73 for hook in known_hooks:
74 _log.debug(hook)
75
76
77 hook_module = None
78
80
81 global hook_module
82 if not reimport:
83 if hook_module is not None:
84 return True
85
86
87
88
89 script_name = 'hook_script.py'
90 script_path = os.path.expanduser(os.path.join('~', '.gnumed', 'scripts'))
91 full_script = os.path.join(script_path, script_name)
92
93 if not os.access(full_script, os.F_OK):
94 _log.warning('creating default hook script')
95 f = open(full_script, 'w')
96 f.write("""
97 # known hooks:
98 # %s
99
100 def run_script(hook=None):
101 pass
102 """ % '# '.join(known_hooks))
103 f.close()
104 os.chmod(full_script, 384)
105
106 if os.path.islink(full_script):
107 gmDispatcher.send (
108 signal = 'statustext',
109 msg = _('Script must not be a link: [%s].') % full_script
110 )
111 return False
112
113 if not os.access(full_script, os.R_OK):
114 gmDispatcher.send (
115 signal = 'statustext',
116 msg = _('Script must be readable by the calling user: [%s].') % full_script
117 )
118 return False
119
120 script_stat_val = os.stat(full_script)
121 _log.debug('hook script stat(): %s', script_stat_val)
122 script_perms = stat.S_IMODE(script_stat_val.st_mode)
123 _log.debug('hook script mode: %s (oktal: %s)', script_perms, oct(script_perms))
124 if script_perms != 384:
125 if os.name in ['nt']:
126 _log.warning('this platform does not support os.stat() file permission checking')
127 else:
128 gmDispatcher.send (
129 signal = 'statustext',
130 msg = _('Script must be readable by the calling user only (permissions "0600"): [%s].') % full_script
131 )
132 return False
133
134 try:
135 tmp = gmTools.import_module_from_directory(script_path, script_name)
136 except StandardError:
137 _log.exception('cannot import hook script')
138 return False
139
140 hook_module = tmp
141
142
143
144 _log.info('hook script: %s', full_script)
145 return True
146
148
149
150 if hook not in known_hooks:
151 raise ValueError('run_hook_script(): unknown hook [%s]' % hook)
152
153 if not import_hook_module(reimport = False):
154 return False
155
156 try:
157 hook_module.run_script(hook = hook)
158 except StandardError:
159 _log.exception('error running hook script for [%s]', hook)
160 gmDispatcher.send (
161 signal = u'statustext',
162 msg = _('Error running hook [%s] script.') % hook,
163 beep = True
164 )
165 return False
166
167 return True
168
169 if __name__ == '__main__':
170
171 run_hook_script(hook = 'shutdown-post-GUI')
172 run_hook_script(hook = 'invalid hook')
173
174
175