1
2 __doc__ = """GNUmed general tools."""
3
4
5 __author__ = "K. Hilbert <Karsten.Hilbert@gmx.net>"
6 __license__ = "GPL v2 or later (details at http://www.gnu.org)"
7
8
9 import re as regex, sys, os, os.path, csv, tempfile, logging, hashlib
10 import decimal
11 import cPickle, zlib
12
13
14
15 if __name__ == '__main__':
16
17 logging.basicConfig(level = logging.DEBUG)
18 sys.path.insert(0, '../../')
19 from Gnumed.pycommon import gmI18N
20 gmI18N.activate_locale()
21 gmI18N.install_domain()
22
23 from Gnumed.pycommon import gmBorg
24
25
26 _log = logging.getLogger('gm.tools')
27
28
29 ( CAPS_NONE,
30 CAPS_FIRST,
31 CAPS_ALLCAPS,
32 CAPS_WORDS,
33 CAPS_NAMES,
34 CAPS_FIRST_ONLY
35 ) = range(6)
36
37
38 u_right_double_angle_quote = u'\u00AB'
39 u_registered_trademark = u'\u00AE'
40 u_plus_minus = u'\u00B1'
41 u_left_double_angle_quote = u'\u00BB'
42 u_one_quarter = u'\u00BC'
43 u_one_half = u'\u00BD'
44 u_three_quarters = u'\u00BE'
45 u_ellipsis = u'\u2026'
46 u_down_left_arrow = u'\u21B5'
47 u_left_arrow = u'\u2190'
48 u_right_arrow = u'\u2192'
49 u_sum = u'\u2211'
50 u_corresponds_to = u'\u2258'
51 u_infinity = u'\u221E'
52 u_diameter = u'\u2300'
53 u_checkmark_crossed_out = u'\u237B'
54 u_box_horiz_single = u'\u2500'
55 u_box_horiz_4dashes = u'\u2508'
56 u_box_top_double = u'\u2550'
57 u_box_top_left_double_single = u'\u2552'
58 u_box_top_right_double_single = u'\u2555'
59 u_box_top_left_arc = u'\u256d'
60 u_box_bottom_right_arc = u'\u256f'
61 u_box_bottom_left_arc = u'\u2570'
62 u_box_horiz_light_heavy = u'\u257c'
63 u_box_horiz_heavy_light = u'\u257e'
64 u_skull_and_crossbones = u'\u2620'
65 u_frowning_face = u'\u2639'
66 u_smiling_face = u'\u263a'
67 u_black_heart = u'\u2665'
68 u_checkmark_thin = u'\u2713'
69 u_checkmark_thick = u'\u2714'
70 u_writing_hand = u'\u270d'
71 u_pencil_1 = u'\u270e'
72 u_pencil_2 = u'\u270f'
73 u_pencil_3 = u'\u2710'
74 u_latin_cross = u'\u271d'
75 u_replacement_character = u'\ufffd'
76 u_link_symbol = u'\u1f517'
77
78
80
81 print ".========================================================"
82 print "| Unhandled exception caught !"
83 print "| Type :", t
84 print "| Value:", v
85 print "`========================================================"
86 _log.critical('unhandled exception caught', exc_info = (t,v,tb))
87 sys.__excepthook__(t,v,tb)
88
89
90
91 -def mkdir(directory=None):
92 try:
93 os.makedirs(directory)
94 except OSError, e:
95 if (e.errno == 17) and not os.path.isdir(directory):
96 raise
97 return True
98
99
101 """This class provides the following paths:
102
103 .home_dir
104 .local_base_dir
105 .working_dir
106 .user_config_dir
107 .system_config_dir
108 .system_app_data_dir
109 .tmp_dir (readonly)
110 """
111 - def __init__(self, app_name=None, wx=None):
112 """Setup pathes.
113
114 <app_name> will default to (name of the script - .py)
115 """
116 try:
117 self.already_inited
118 return
119 except AttributeError:
120 pass
121
122 self.init_paths(app_name=app_name, wx=wx)
123 self.already_inited = True
124
125
126
128
129 if wx is None:
130 _log.debug('wxPython not available')
131 _log.debug('detecting paths directly')
132
133 if app_name is None:
134 app_name, ext = os.path.splitext(os.path.basename(sys.argv[0]))
135 _log.info('app name detected as [%s]', app_name)
136 else:
137 _log.info('app name passed in as [%s]', app_name)
138
139
140 self.__home_dir = None
141
142
143
144 self.local_base_dir = os.path.abspath(os.path.dirname(sys.argv[0]))
145
146
147 self.working_dir = os.path.abspath(os.curdir)
148
149
150
151
152 mkdir(os.path.join(self.home_dir, '.%s' % app_name))
153 self.user_config_dir = os.path.join(self.home_dir, '.%s' % app_name)
154
155
156 try:
157 self.system_config_dir = os.path.join('/etc', app_name)
158 except ValueError:
159
160 self.system_config_dir = self.user_config_dir
161
162
163 try:
164 self.system_app_data_dir = os.path.join(sys.prefix, 'share', app_name)
165 except ValueError:
166 self.system_app_data_dir = self.local_base_dir
167
168
169 try:
170 self.__tmp_dir_already_set
171 _log.debug('temp dir already set')
172 except AttributeError:
173 tmp_base = os.path.join(tempfile.gettempdir(), app_name)
174 mkdir(tmp_base)
175 _log.info('previous temp dir: %s', tempfile.gettempdir())
176 tempfile.tempdir = tmp_base
177 _log.info('intermediate temp dir: %s', tempfile.gettempdir())
178 self.tmp_dir = tempfile.mkdtemp(prefix = r'gm-')
179
180 self.__log_paths()
181 if wx is None:
182 return True
183
184
185 _log.debug('re-detecting paths with wxPython')
186
187 std_paths = wx.StandardPaths.Get()
188 _log.info('wxPython app name is [%s]', wx.GetApp().GetAppName())
189
190
191 mkdir(os.path.join(std_paths.GetUserConfigDir(), '.%s' % app_name))
192 self.user_config_dir = os.path.join(std_paths.GetUserConfigDir(), '.%s' % app_name)
193
194
195 try:
196 tmp = std_paths.GetConfigDir()
197 if not tmp.endswith(app_name):
198 tmp = os.path.join(tmp, app_name)
199 self.system_config_dir = tmp
200 except ValueError:
201
202 pass
203
204
205
206
207 if 'wxMSW' in wx.PlatformInfo:
208 _log.warning('this platform (wxMSW) sometimes returns a broken value for the system-wide application data dir')
209 else:
210 try:
211 self.system_app_data_dir = std_paths.GetDataDir()
212 except ValueError:
213 pass
214
215 self.__log_paths()
216 return True
217
219 _log.debug('sys.argv[0]: %s', sys.argv[0])
220 _log.debug('local application base dir: %s', self.local_base_dir)
221 _log.debug('current working dir: %s', self.working_dir)
222
223 _log.debug('user home dir: %s', self.home_dir)
224 _log.debug('user-specific config dir: %s', self.user_config_dir)
225 _log.debug('system-wide config dir: %s', self.system_config_dir)
226 _log.debug('system-wide application data dir: %s', self.system_app_data_dir)
227 _log.debug('temporary dir: %s', self.tmp_dir)
228
229
230
232 if not (os.access(path, os.R_OK) and os.access(path, os.X_OK)):
233 msg = '[%s:user_config_dir]: invalid path [%s]' % (self.__class__.__name__, path)
234 _log.error(msg)
235 raise ValueError(msg)
236 self.__user_config_dir = path
237
239 return self.__user_config_dir
240
241 user_config_dir = property(_get_user_config_dir, _set_user_config_dir)
242
244 if not (os.access(path, os.R_OK) and os.access(path, os.X_OK)):
245 msg = '[%s:system_config_dir]: invalid path [%s]' % (self.__class__.__name__, path)
246 _log.error(msg)
247 raise ValueError(msg)
248 self.__system_config_dir = path
249
251 return self.__system_config_dir
252
253 system_config_dir = property(_get_system_config_dir, _set_system_config_dir)
254
256 if not (os.access(path, os.R_OK) and os.access(path, os.X_OK)):
257 msg = '[%s:system_app_data_dir]: invalid path [%s]' % (self.__class__.__name__, path)
258 _log.error(msg)
259 raise ValueError(msg)
260 self.__system_app_data_dir = path
261
263 return self.__system_app_data_dir
264
265 system_app_data_dir = property(_get_system_app_data_dir, _set_system_app_data_dir)
266
268 raise ValueError('invalid to set home dir')
269
271 if self.__home_dir is not None:
272 return self.__home_dir
273
274 tmp = os.path.expanduser('~')
275 if tmp == '~':
276 _log.error('this platform does not expand ~ properly')
277 try:
278 tmp = os.environ['USERPROFILE']
279 except KeyError:
280 _log.error('cannot access $USERPROFILE in environment')
281
282 if not (
283 os.access(tmp, os.R_OK)
284 and
285 os.access(tmp, os.X_OK)
286 and
287 os.access(tmp, os.W_OK)
288 ):
289 msg = '[%s:home_dir]: invalid path [%s]' % (self.__class__.__name__, tmp)
290 _log.error(msg)
291 raise ValueError(msg)
292
293 self.__home_dir = tmp
294 return self.__home_dir
295
296 home_dir = property(_get_home_dir, _set_home_dir)
297
299 if not (os.access(path, os.R_OK) and os.access(path, os.X_OK)):
300 msg = '[%s:tmp_dir]: invalid path [%s]' % (self.__class__.__name__, path)
301 _log.error(msg)
302 raise ValueError(msg)
303 _log.debug('previous temp dir: %s', tempfile.gettempdir())
304 self.__tmp_dir = path
305 tempfile.tempdir = self.__tmp_dir
306 self.__tmp_dir_already_set = True
307
309 return self.__tmp_dir
310
311 tmp_dir = property(_get_tmp_dir, _set_tmp_dir)
312
313
314
315 -def file2md5(filename=None, return_hex=True):
316 blocksize = 2**10 * 128
317 _log.debug('md5(%s): <%s> byte blocks', filename, blocksize)
318
319 f = open(filename, 'rb')
320
321 md5 = hashlib.md5()
322 while True:
323 data = f.read(blocksize)
324 if not data:
325 break
326 md5.update(data)
327
328 _log.debug('md5(%s): %s', filename, md5.hexdigest())
329
330 if return_hex:
331 return md5.hexdigest()
332 return md5.digest()
333
335 for line in unicode_csv_data:
336 yield line.encode(encoding)
337
338
339
340
341
342 default_csv_reader_rest_key = u'list_of_values_of_unknown_fields'
343
345
346
347 try:
348 is_dict_reader = kwargs['dict']
349 del kwargs['dict']
350 if is_dict_reader is not True:
351 raise KeyError
352 kwargs['restkey'] = default_csv_reader_rest_key
353 csv_reader = csv.DictReader(unicode2charset_encoder(unicode_csv_data), dialect=dialect, **kwargs)
354 except KeyError:
355 is_dict_reader = False
356 csv_reader = csv.reader(unicode2charset_encoder(unicode_csv_data), dialect=dialect, **kwargs)
357
358 for row in csv_reader:
359
360 if is_dict_reader:
361 for key in row.keys():
362 if key == default_csv_reader_rest_key:
363 old_data = row[key]
364 new_data = []
365 for val in old_data:
366 new_data.append(unicode(val, encoding))
367 row[key] = new_data
368 if default_csv_reader_rest_key not in csv_reader.fieldnames:
369 csv_reader.fieldnames.append(default_csv_reader_rest_key)
370 else:
371 row[key] = unicode(row[key], encoding)
372 yield row
373 else:
374 yield [ unicode(cell, encoding) for cell in row ]
375
376
378 """This introduces a race condition between the file.close() and
379 actually using the filename.
380
381 The file will not exist after calling this function.
382 """
383 if tmp_dir is not None:
384 if (
385 not os.access(tmp_dir, os.F_OK)
386 or
387 not os.access(tmp_dir, os.X_OK | os.W_OK)
388 ):
389 _log.info('cannot find temporary dir [%s], using system default', tmp_dir)
390 tmp_dir = None
391
392 kwargs = {'dir': tmp_dir}
393
394 if prefix is None:
395 kwargs['prefix'] = 'gnumed-'
396 else:
397 kwargs['prefix'] = prefix
398
399 if suffix in [None, u'']:
400 kwargs['suffix'] = '.tmp'
401 else:
402 if not suffix.startswith('.'):
403 suffix = '.' + suffix
404 kwargs['suffix'] = suffix
405
406 f = tempfile.NamedTemporaryFile(**kwargs)
407 filename = f.name
408 f.close()
409
410 return filename
411
413 """Import a module from any location."""
414
415 remove_path = always_remove_path or False
416 if module_path not in sys.path:
417 _log.info('appending to sys.path: [%s]' % module_path)
418 sys.path.append(module_path)
419 remove_path = True
420
421 _log.debug('will remove import path: %s', remove_path)
422
423 if module_name.endswith('.py'):
424 module_name = module_name[:-3]
425
426 try:
427 module = __import__(module_name)
428 except StandardError:
429 _log.exception('cannot __import__() module [%s] from [%s]' % (module_name, module_path))
430 while module_path in sys.path:
431 sys.path.remove(module_path)
432 raise
433
434 _log.info('imported module [%s] as [%s]' % (module_name, module))
435 if remove_path:
436 while module_path in sys.path:
437 sys.path.remove(module_path)
438
439 return module
440
441
442
443 _kB = 1024
444 _MB = 1024 * _kB
445 _GB = 1024 * _MB
446 _TB = 1024 * _GB
447 _PB = 1024 * _TB
448
450 if size == 1:
451 return template % _('1 Byte')
452 if size < 10 * _kB:
453 return template % _('%s Bytes') % size
454 if size < _MB:
455 return template % u'%.1f kB' % (float(size) / _kB)
456 if size < _GB:
457 return template % u'%.1f MB' % (float(size) / _MB)
458 if size < _TB:
459 return template % u'%.1f GB' % (float(size) / _GB)
460 if size < _PB:
461 return template % u'%.1f TB' % (float(size) / _TB)
462 return template % u'%.1f PB' % (float(size) / _PB)
463
464 -def bool2subst(boolean=None, true_return=True, false_return=False, none_return=None):
465 if boolean is None:
466 return none_return
467 if boolean is True:
468 return true_return
469 if boolean is False:
470 return false_return
471 raise ValueError('bool2subst(): <boolean> arg must be either of True, False, None')
472
473 -def bool2str(boolean=None, true_str='True', false_str='False'):
474 return bool2subst (
475 boolean = bool(boolean),
476 true_return = true_str,
477 false_return = false_str
478 )
479
480 -def none_if(value=None, none_equivalent=None, strip_string=False):
481 """Modelled after the SQL NULLIF function."""
482 if value is None:
483 return None
484 if strip_string:
485 stripped = value.strip()
486 else:
487 stripped = value
488 if stripped == none_equivalent:
489 return None
490 return value
491
492 -def coalesce(initial=None, instead=None, template_initial=None, template_instead=None, none_equivalents=None, function_initial=None):
493 """Modelled after the SQL coalesce function.
494
495 To be used to simplify constructs like:
496
497 if initial is None (or in none_equivalents):
498 real_value = (template_instead % instead) or instead
499 else:
500 real_value = (template_initial % initial) or initial
501 print real_value
502
503 @param initial: the value to be tested for <None>
504 @type initial: any Python type, must have a __str__ method if template_initial is not None
505 @param instead: the value to be returned if <initial> is None
506 @type instead: any Python type, must have a __str__ method if template_instead is not None
507 @param template_initial: if <initial> is returned replace the value into this template, must contain one <%s>
508 @type template_initial: string or None
509 @param template_instead: if <instead> is returned replace the value into this template, must contain one <%s>
510 @type template_instead: string or None
511
512 example:
513 function_initial = ('strftime', '%Y-%m-%d')
514
515 Ideas:
516 - list of insteads: initial, [instead, template], [instead, template], [instead, template], template_initial, ...
517 """
518 if none_equivalents is None:
519 none_equivalents = [None]
520
521 if initial in none_equivalents:
522
523 if template_instead is None:
524 return instead
525
526 return template_instead % instead
527
528 if function_initial is not None:
529 funcname, args = function_initial
530 func = getattr(initial, funcname)
531 initial = func(args)
532
533 if template_initial is None:
534 return initial
535
536 try:
537 return template_initial % initial
538 except TypeError:
539 return template_initial
540
542 val = match_obj.group(0).lower()
543 if val in ['von', 'van', 'de', 'la', 'l', 'der', 'den']:
544 return val
545 buf = list(val)
546 buf[0] = buf[0].upper()
547 for part in ['mac', 'mc', 'de', 'la']:
548 if len(val) > len(part) and val[:len(part)] == part:
549 buf[len(part)] = buf[len(part)].upper()
550 return ''.join(buf)
551
553 """Capitalize the first character but leave the rest alone.
554
555 Note that we must be careful about the locale, this may
556 have issues ! However, for UTF strings it should just work.
557 """
558 if (mode is None) or (mode == CAPS_NONE):
559 return text
560
561 if mode == CAPS_FIRST:
562 if len(text) == 1:
563 return text[0].upper()
564 return text[0].upper() + text[1:]
565
566 if mode == CAPS_ALLCAPS:
567 return text.upper()
568
569 if mode == CAPS_FIRST_ONLY:
570 if len(text) == 1:
571 return text[0].upper()
572 return text[0].upper() + text[1:].lower()
573
574 if mode == CAPS_WORDS:
575 return regex.sub(ur'(\w)(\w+)', lambda x: x.group(1).upper() + x.group(2).lower(), text)
576
577 if mode == CAPS_NAMES:
578
579 return capitalize(text=text, mode=CAPS_FIRST)
580
581 print "ERROR: invalid capitalization mode: [%s], leaving input as is" % mode
582 return text
583
605
631
632 -def wrap(text=None, width=None, initial_indent=u'', subsequent_indent=u'', eol=u'\n'):
633 """A word-wrap function that preserves existing line breaks
634 and most spaces in the text. Expects that existing line
635 breaks are posix newlines (\n).
636 """
637 wrapped = initial_indent + reduce (
638 lambda line, word, width=width: '%s%s%s' % (
639 line,
640 ' \n'[(len(line) - line.rfind('\n') - 1 + len(word.split('\n',1)[0]) >= width)],
641 word
642 ),
643 text.split(' ')
644 )
645
646 if subsequent_indent != u'':
647 wrapped = (u'\n%s' % subsequent_indent).join(wrapped.split('\n'))
648
649 if eol != u'\n':
650 wrapped = wrapped.replace('\n', eol)
651
652 return wrapped
653
654 -def unwrap(text=None, max_length=None, strip_whitespace=True, remove_empty_lines=True, line_separator = u' // '):
655
656 text = text.replace(u'\r', u'')
657 lines = text.split(u'\n')
658 text = u''
659 for line in lines:
660
661 if strip_whitespace:
662 line = line.strip().strip(u'\t').strip()
663
664 if remove_empty_lines:
665 if line == u'':
666 continue
667
668 text += (u'%s%s' % (line, line_separator))
669
670 text = text.rstrip(line_separator)
671
672 if max_length is not None:
673 text = text[:max_length]
674
675 text = text.rstrip(line_separator)
676
677 return text
678
680 """check for special XML characters and transform them"""
681
682 text = text.replace(u'&', u'&')
683
684 return text
685
687 """check for special LaTeX characters and transform them"""
688
689 text = text.replace(u'\\', u'$\\backslash$')
690 text = text.replace(u'{', u'\\{')
691 text = text.replace(u'}', u'\\}')
692 text = text.replace(u'%', u'\\%')
693 text = text.replace(u'&', u'\\&')
694 text = text.replace(u'#', u'\\#')
695 text = text.replace(u'$', u'\\$')
696 text = text.replace(u'_', u'\\_')
697
698 text = text.replace(u'^', u'\\verb#^#')
699 text = text.replace('~','\\verb#~#')
700
701 return text
702
729
730
731
732
733
734 __icon_serpent = \
735 """x\xdae\x8f\xb1\x0e\x83 \x10\x86w\x9f\xe2\x92\x1blb\xf2\x07\x96\xeaH:0\xd6\
736 \xc1\x85\xd5\x98N5\xa5\xef?\xf5N\xd0\x8a\xdcA\xc2\xf7qw\x84\xdb\xfa\xb5\xcd\
737 \xd4\xda;\xc9\x1a\xc8\xb6\xcd<\xb5\xa0\x85\x1e\xeb\xbc\xbc7b!\xf6\xdeHl\x1c\
738 \x94\x073\xec<*\xf7\xbe\xf7\x99\x9d\xb21~\xe7.\xf5\x1f\x1c\xd3\xbdVlL\xc2\
739 \xcf\xf8ye\xd0\x00\x90\x0etH \x84\x80B\xaa\x8a\x88\x85\xc4(U\x9d$\xfeR;\xc5J\
740 \xa6\x01\xbbt9\xceR\xc8\x81e_$\x98\xb9\x9c\xa9\x8d,y\xa9t\xc8\xcf\x152\xe0x\
741 \xe9$\xf5\x07\x95\x0cD\x95t:\xb1\x92\xae\x9cI\xa8~\x84\x1f\xe0\xa3ec"""
742
744
745 paths = gmPaths(app_name = u'gnumed', wx = wx)
746
747 candidates = [
748 os.path.join(paths.system_app_data_dir, 'bitmaps', 'gm_icon-serpent_and_gnu.png'),
749 os.path.join(paths.local_base_dir, 'bitmaps', 'gm_icon-serpent_and_gnu.png'),
750 os.path.join(paths.system_app_data_dir, 'bitmaps', 'serpent.png'),
751 os.path.join(paths.local_base_dir, 'bitmaps', 'serpent.png')
752 ]
753
754 found_as = None
755 for candidate in candidates:
756 try:
757 open(candidate, 'r').close()
758 found_as = candidate
759 break
760 except IOError:
761 _log.debug('icon not found in [%s]', candidate)
762
763 if found_as is None:
764 _log.warning('no icon file found, falling back to builtin (ugly) icon')
765 icon_bmp_data = wx.BitmapFromXPMData(cPickle.loads(zlib.decompress(__icon_serpent)))
766 icon.CopyFromBitmap(icon_bmp_data)
767 else:
768 _log.debug('icon found in [%s]', found_as)
769 icon = wx.EmptyIcon()
770 try:
771 icon.LoadFile(found_as, wx.BITMAP_TYPE_ANY)
772 except AttributeError:
773 _log.exception(u"this platform doesn't support wx.Icon().LoadFile()")
774
775 return icon
776
777
778
779 if __name__ == '__main__':
780
781 if len(sys.argv) < 2:
782 sys.exit()
783
784 if sys.argv[1] != 'test':
785 sys.exit()
786
787
845
850
852
853 import datetime as dt
854 print coalesce(initial = dt.datetime.now(), template_initial = u'-- %s --', function_initial = ('strftime', u'%Y-%m-%d'))
855
856 print 'testing coalesce()'
857 print "------------------"
858 tests = [
859 [None, 'something other than <None>', None, None, 'something other than <None>'],
860 ['Captain', 'Mr.', '%s.'[:4], 'Mr.', 'Capt.'],
861 ['value to test', 'test 3 failed', 'template with "%s" included', None, 'template with "value to test" included'],
862 ['value to test', 'test 4 failed', 'template with value not included', None, 'template with value not included'],
863 [None, 'initial value was None', 'template_initial: %s', None, 'initial value was None'],
864 [None, 'initial value was None', 'template_initial: %%(abc)s', None, 'initial value was None']
865 ]
866 passed = True
867 for test in tests:
868 result = coalesce (
869 initial = test[0],
870 instead = test[1],
871 template_initial = test[2],
872 template_instead = test[3]
873 )
874 if result != test[4]:
875 print "ERROR"
876 print "coalesce: (%s, %s, %s, %s)" % (test[0], test[1], test[2], test[3])
877 print "expected:", test[4]
878 print "received:", result
879 passed = False
880
881 if passed:
882 print "passed"
883 else:
884 print "failed"
885 return passed
886
888 print 'testing capitalize() ...'
889 success = True
890 pairs = [
891
892 [u'Boot', u'Boot', CAPS_FIRST_ONLY],
893 [u'boot', u'Boot', CAPS_FIRST_ONLY],
894 [u'booT', u'Boot', CAPS_FIRST_ONLY],
895 [u'BoOt', u'Boot', CAPS_FIRST_ONLY],
896 [u'boots-Schau', u'Boots-Schau', CAPS_WORDS],
897 [u'boots-sChau', u'Boots-Schau', CAPS_WORDS],
898 [u'boot camp', u'Boot Camp', CAPS_WORDS],
899 [u'fahrner-Kampe', u'Fahrner-Kampe', CAPS_NAMES],
900 [u'häkkönen', u'Häkkönen', CAPS_NAMES],
901 [u'McBurney', u'McBurney', CAPS_NAMES],
902 [u'mcBurney', u'McBurney', CAPS_NAMES],
903 [u'blumberg', u'Blumberg', CAPS_NAMES],
904 [u'roVsing', u'RoVsing', CAPS_NAMES],
905 [u'Özdemir', u'Özdemir', CAPS_NAMES],
906 [u'özdemir', u'Özdemir', CAPS_NAMES],
907 ]
908 for pair in pairs:
909 result = capitalize(pair[0], pair[2])
910 if result != pair[1]:
911 success = False
912 print 'ERROR (caps mode %s): "%s" -> "%s", expected "%s"' % (pair[2], pair[0], result, pair[1])
913
914 if success:
915 print "... SUCCESS"
916
917 return success
918
920 print "testing import_module_from_directory()"
921 path = sys.argv[1]
922 name = sys.argv[2]
923 try:
924 mod = import_module_from_directory(module_path = path, module_name = name)
925 except:
926 print "module import failed, see log"
927 return False
928
929 print "module import succeeded", mod
930 print dir(mod)
931 return True
932
934 print "testing mkdir()"
935 mkdir(sys.argv[1])
936
938 print "testing gmPaths()"
939 print "-----------------"
940 paths = gmPaths(wx=None, app_name='gnumed')
941 print "user config dir:", paths.user_config_dir
942 print "system config dir:", paths.system_config_dir
943 print "local base dir:", paths.local_base_dir
944 print "system app data dir:", paths.system_app_data_dir
945 print "working directory :", paths.working_dir
946 print "temp directory :", paths.tmp_dir
947
949 print "testing none_if()"
950 print "-----------------"
951 tests = [
952 [None, None, None],
953 ['a', 'a', None],
954 ['a', 'b', 'a'],
955 ['a', None, 'a'],
956 [None, 'a', None],
957 [1, 1, None],
958 [1, 2, 1],
959 [1, None, 1],
960 [None, 1, None]
961 ]
962
963 for test in tests:
964 if none_if(value = test[0], none_equivalent = test[1]) != test[2]:
965 print 'ERROR: none_if(%s) returned [%s], expected [%s]' % (test[0], none_if(test[0], test[1]), test[2])
966
967 return True
968
970 tests = [
971 [True, 'Yes', 'Yes', 'Yes'],
972 [False, 'OK', 'not OK', 'not OK']
973 ]
974 for test in tests:
975 if bool2str(test[0], test[1], test[2]) != test[3]:
976 print 'ERROR: bool2str(%s, %s, %s) returned [%s], expected [%s]' % (test[0], test[1], test[2], bool2str(test[0], test[1], test[2]), test[3])
977
978 return True
979
981
982 print bool2subst(True, 'True', 'False', 'is None')
983 print bool2subst(False, 'True', 'False', 'is None')
984 print bool2subst(None, 'True', 'False', 'is None')
985
992
994 print "testing size2str()"
995 print "------------------"
996 tests = [0, 1, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000, 10000000000, 100000000000, 1000000000000, 10000000000000]
997 for test in tests:
998 print size2str(test)
999
1001
1002 test = """
1003 second line\n
1004 3rd starts with tab \n
1005 4th with a space \n
1006
1007 6th
1008
1009 """
1010 print unwrap(text = test, max_length = 25)
1011
1013 test = 'line 1\nline 2\nline 3'
1014
1015 print "wrap 5-6-7 initial 0, subsequent 0"
1016 print wrap(test, 5)
1017 print
1018 print wrap(test, 6)
1019 print
1020 print wrap(test, 7)
1021 print "-------"
1022 raw_input()
1023 print "wrap 5 initial 1-1-3, subsequent 1-3-1"
1024 print wrap(test, 5, u' ', u' ')
1025 print
1026 print wrap(test, 5, u' ', u' ')
1027 print
1028 print wrap(test, 5, u' ', u' ')
1029 print "-------"
1030 raw_input()
1031 print "wrap 6 initial 1-1-3, subsequent 1-3-1"
1032 print wrap(test, 6, u' ', u' ')
1033 print
1034 print wrap(test, 6, u' ', u' ')
1035 print
1036 print wrap(test, 6, u' ', u' ')
1037 print "-------"
1038 raw_input()
1039 print "wrap 7 initial 1-1-3, subsequent 1-3-1"
1040 print wrap(test, 7, u' ', u' ')
1041 print
1042 print wrap(test, 7, u' ', u' ')
1043 print
1044 print wrap(test, 7, u' ', u' ')
1045
1047 print '%s: %s' % (sys.argv[2], file2md5(sys.argv[2]))
1048
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067 test_unicode()
1068
1069
1070