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
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):
481 """Modelled after the SQL NULLIF function."""
482 if value == none_equivalent:
483 return None
484 return value
485
486 -def coalesce(initial=None, instead=None, template_initial=None, template_instead=None, none_equivalents=None, function_initial=None):
487 """Modelled after the SQL coalesce function.
488
489 To be used to simplify constructs like:
490
491 if initial is None (or in none_equivalents):
492 real_value = (template_instead % instead) or instead
493 else:
494 real_value = (template_initial % initial) or initial
495 print real_value
496
497 @param initial: the value to be tested for <None>
498 @type initial: any Python type, must have a __str__ method if template_initial is not None
499 @param instead: the value to be returned if <initial> is None
500 @type instead: any Python type, must have a __str__ method if template_instead is not None
501 @param template_initial: if <initial> is returned replace the value into this template, must contain one <%s>
502 @type template_initial: string or None
503 @param template_instead: if <instead> is returned replace the value into this template, must contain one <%s>
504 @type template_instead: string or None
505
506 example:
507 function_initial = ('strftime', '%Y-%m-%d')
508
509 Ideas:
510 - list of insteads: initial, [instead, template], [instead, template], [instead, template], template_initial, ...
511 """
512 if none_equivalents is None:
513 none_equivalents = [None]
514
515 if initial in none_equivalents:
516
517 if template_instead is None:
518 return instead
519
520 return template_instead % instead
521
522 if function_initial is not None:
523 funcname, args = function_initial
524 func = getattr(initial, funcname)
525 initial = func(args)
526
527 if template_initial is None:
528 return initial
529
530 try:
531 return template_initial % initial
532 except TypeError:
533 return template_initial
534
536 val = match_obj.group(0).lower()
537 if val in ['von', 'van', 'de', 'la', 'l', 'der', 'den']:
538 return val
539 buf = list(val)
540 buf[0] = buf[0].upper()
541 for part in ['mac', 'mc', 'de', 'la']:
542 if len(val) > len(part) and val[:len(part)] == part:
543 buf[len(part)] = buf[len(part)].upper()
544 return ''.join(buf)
545
547 """Capitalize the first character but leave the rest alone.
548
549 Note that we must be careful about the locale, this may
550 have issues ! However, for UTF strings it should just work.
551 """
552 if (mode is None) or (mode == CAPS_NONE):
553 return text
554
555 if mode == CAPS_FIRST:
556 if len(text) == 1:
557 return text[0].upper()
558 return text[0].upper() + text[1:]
559
560 if mode == CAPS_ALLCAPS:
561 return text.upper()
562
563 if mode == CAPS_FIRST_ONLY:
564 if len(text) == 1:
565 return text[0].upper()
566 return text[0].upper() + text[1:].lower()
567
568 if mode == CAPS_WORDS:
569 return regex.sub(ur'(\w)(\w+)', lambda x: x.group(1).upper() + x.group(2).lower(), text)
570
571 if mode == CAPS_NAMES:
572
573 return capitalize(text=text, mode=CAPS_FIRST)
574
575 print "ERROR: invalid capitalization mode: [%s], leaving input as is" % mode
576 return text
577
599
625
626 -def wrap(text=None, width=None, initial_indent=u'', subsequent_indent=u'', eol=u'\n'):
627 """A word-wrap function that preserves existing line breaks
628 and most spaces in the text. Expects that existing line
629 breaks are posix newlines (\n).
630 """
631 wrapped = initial_indent + reduce (
632 lambda line, word, width=width: '%s%s%s' % (
633 line,
634 ' \n'[(len(line) - line.rfind('\n') - 1 + len(word.split('\n',1)[0]) >= width)],
635 word
636 ),
637 text.split(' ')
638 )
639
640 if subsequent_indent != u'':
641 wrapped = (u'\n%s' % subsequent_indent).join(wrapped.split('\n'))
642
643 if eol != u'\n':
644 wrapped = wrapped.replace('\n', eol)
645
646 return wrapped
647
648 -def unwrap(text=None, max_length=None, strip_whitespace=True, remove_empty_lines=True, line_separator = u' // '):
649
650 text = text.replace(u'\r', u'')
651 lines = text.split(u'\n')
652 text = u''
653 for line in lines:
654
655 if strip_whitespace:
656 line = line.strip().strip(u'\t').strip()
657
658 if remove_empty_lines:
659 if line == u'':
660 continue
661
662 text += (u'%s%s' % (line, line_separator))
663
664 text = text.rstrip(line_separator)
665
666 if max_length is not None:
667 text = text[:max_length]
668
669 text = text.rstrip(line_separator)
670
671 return text
672
674 """check for special XML characters and transform them"""
675
676 text = text.replace(u'&', u'&')
677
678 return text
679
681 """check for special LaTeX characters and transform them"""
682
683 text = text.replace(u'\\', u'$\\backslash$')
684 text = text.replace(u'{', u'\\{')
685 text = text.replace(u'}', u'\\}')
686 text = text.replace(u'%', u'\\%')
687 text = text.replace(u'&', u'\\&')
688 text = text.replace(u'#', u'\\#')
689 text = text.replace(u'$', u'\\$')
690 text = text.replace(u'_', u'\\_')
691
692 text = text.replace(u'^', u'\\verb#^#')
693 text = text.replace('~','\\verb#~#')
694
695 return text
696
723
724
725
726
727
728 __icon_serpent = \
729 """x\xdae\x8f\xb1\x0e\x83 \x10\x86w\x9f\xe2\x92\x1blb\xf2\x07\x96\xeaH:0\xd6\
730 \xc1\x85\xd5\x98N5\xa5\xef?\xf5N\xd0\x8a\xdcA\xc2\xf7qw\x84\xdb\xfa\xb5\xcd\
731 \xd4\xda;\xc9\x1a\xc8\xb6\xcd<\xb5\xa0\x85\x1e\xeb\xbc\xbc7b!\xf6\xdeHl\x1c\
732 \x94\x073\xec<*\xf7\xbe\xf7\x99\x9d\xb21~\xe7.\xf5\x1f\x1c\xd3\xbdVlL\xc2\
733 \xcf\xf8ye\xd0\x00\x90\x0etH \x84\x80B\xaa\x8a\x88\x85\xc4(U\x9d$\xfeR;\xc5J\
734 \xa6\x01\xbbt9\xceR\xc8\x81e_$\x98\xb9\x9c\xa9\x8d,y\xa9t\xc8\xcf\x152\xe0x\
735 \xe9$\xf5\x07\x95\x0cD\x95t:\xb1\x92\xae\x9cI\xa8~\x84\x1f\xe0\xa3ec"""
736
738
739 paths = gmPaths(app_name = u'gnumed', wx = wx)
740
741 candidates = [
742 os.path.join(paths.system_app_data_dir, 'bitmaps', 'gm_icon-serpent_and_gnu.png'),
743 os.path.join(paths.local_base_dir, 'bitmaps', 'gm_icon-serpent_and_gnu.png'),
744 os.path.join(paths.system_app_data_dir, 'bitmaps', 'serpent.png'),
745 os.path.join(paths.local_base_dir, 'bitmaps', 'serpent.png')
746 ]
747
748 found_as = None
749 for candidate in candidates:
750 try:
751 open(candidate, 'r').close()
752 found_as = candidate
753 break
754 except IOError:
755 _log.debug('icon not found in [%s]', candidate)
756
757 if found_as is None:
758 _log.warning('no icon file found, falling back to builtin (ugly) icon')
759 icon_bmp_data = wx.BitmapFromXPMData(cPickle.loads(zlib.decompress(__icon_serpent)))
760 icon.CopyFromBitmap(icon_bmp_data)
761 else:
762 _log.debug('icon found in [%s]', found_as)
763 icon = wx.EmptyIcon()
764 try:
765 icon.LoadFile(found_as, wx.BITMAP_TYPE_ANY)
766 except AttributeError:
767 _log.exception(u"this platform doesn't support wx.Icon().LoadFile()")
768
769 return icon
770
771
772
773 if __name__ == '__main__':
774
775 if len(sys.argv) < 2:
776 sys.exit()
777
778 if sys.argv[1] != 'test':
779 sys.exit()
780
781
839
844
846
847 import datetime as dt
848 print coalesce(initial = dt.datetime.now(), template_initial = u'-- %s --', function_initial = ('strftime', u'%Y-%m-%d'))
849
850 print 'testing coalesce()'
851 print "------------------"
852 tests = [
853 [None, 'something other than <None>', None, None, 'something other than <None>'],
854 ['Captain', 'Mr.', '%s.'[:4], 'Mr.', 'Capt.'],
855 ['value to test', 'test 3 failed', 'template with "%s" included', None, 'template with "value to test" included'],
856 ['value to test', 'test 4 failed', 'template with value not included', None, 'template with value not included'],
857 [None, 'initial value was None', 'template_initial: %s', None, 'initial value was None'],
858 [None, 'initial value was None', 'template_initial: %%(abc)s', None, 'initial value was None']
859 ]
860 passed = True
861 for test in tests:
862 result = coalesce (
863 initial = test[0],
864 instead = test[1],
865 template_initial = test[2],
866 template_instead = test[3]
867 )
868 if result != test[4]:
869 print "ERROR"
870 print "coalesce: (%s, %s, %s, %s)" % (test[0], test[1], test[2], test[3])
871 print "expected:", test[4]
872 print "received:", result
873 passed = False
874
875 if passed:
876 print "passed"
877 else:
878 print "failed"
879 return passed
880
882 print 'testing capitalize() ...'
883 success = True
884 pairs = [
885
886 [u'Boot', u'Boot', CAPS_FIRST_ONLY],
887 [u'boot', u'Boot', CAPS_FIRST_ONLY],
888 [u'booT', u'Boot', CAPS_FIRST_ONLY],
889 [u'BoOt', u'Boot', CAPS_FIRST_ONLY],
890 [u'boots-Schau', u'Boots-Schau', CAPS_WORDS],
891 [u'boots-sChau', u'Boots-Schau', CAPS_WORDS],
892 [u'boot camp', u'Boot Camp', CAPS_WORDS],
893 [u'fahrner-Kampe', u'Fahrner-Kampe', CAPS_NAMES],
894 [u'häkkönen', u'Häkkönen', CAPS_NAMES],
895 [u'McBurney', u'McBurney', CAPS_NAMES],
896 [u'mcBurney', u'McBurney', CAPS_NAMES],
897 [u'blumberg', u'Blumberg', CAPS_NAMES],
898 [u'roVsing', u'RoVsing', CAPS_NAMES],
899 [u'Özdemir', u'Özdemir', CAPS_NAMES],
900 [u'özdemir', u'Özdemir', CAPS_NAMES],
901 ]
902 for pair in pairs:
903 result = capitalize(pair[0], pair[2])
904 if result != pair[1]:
905 success = False
906 print 'ERROR (caps mode %s): "%s" -> "%s", expected "%s"' % (pair[2], pair[0], result, pair[1])
907
908 if success:
909 print "... SUCCESS"
910
911 return success
912
914 print "testing import_module_from_directory()"
915 path = sys.argv[1]
916 name = sys.argv[2]
917 try:
918 mod = import_module_from_directory(module_path = path, module_name = name)
919 except:
920 print "module import failed, see log"
921 return False
922
923 print "module import succeeded", mod
924 print dir(mod)
925 return True
926
928 print "testing mkdir()"
929 mkdir(sys.argv[1])
930
932 print "testing gmPaths()"
933 print "-----------------"
934 paths = gmPaths(wx=None, app_name='gnumed')
935 print "user config dir:", paths.user_config_dir
936 print "system config dir:", paths.system_config_dir
937 print "local base dir:", paths.local_base_dir
938 print "system app data dir:", paths.system_app_data_dir
939 print "working directory :", paths.working_dir
940 print "temp directory :", paths.tmp_dir
941
943 print "testing none_if()"
944 print "-----------------"
945 tests = [
946 [None, None, None],
947 ['a', 'a', None],
948 ['a', 'b', 'a'],
949 ['a', None, 'a'],
950 [None, 'a', None],
951 [1, 1, None],
952 [1, 2, 1],
953 [1, None, 1],
954 [None, 1, None]
955 ]
956
957 for test in tests:
958 if none_if(value = test[0], none_equivalent = test[1]) != test[2]:
959 print 'ERROR: none_if(%s) returned [%s], expected [%s]' % (test[0], none_if(test[0], test[1]), test[2])
960
961 return True
962
964 tests = [
965 [True, 'Yes', 'Yes', 'Yes'],
966 [False, 'OK', 'not OK', 'not OK']
967 ]
968 for test in tests:
969 if bool2str(test[0], test[1], test[2]) != test[3]:
970 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])
971
972 return True
973
975
976 print bool2subst(True, 'True', 'False', 'is None')
977 print bool2subst(False, 'True', 'False', 'is None')
978 print bool2subst(None, 'True', 'False', 'is None')
979
986
988 print "testing size2str()"
989 print "------------------"
990 tests = [0, 1, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000, 10000000000, 100000000000, 1000000000000, 10000000000000]
991 for test in tests:
992 print size2str(test)
993
995
996 test = """
997 second line\n
998 3rd starts with tab \n
999 4th with a space \n
1000
1001 6th
1002
1003 """
1004 print unwrap(text = test, max_length = 25)
1005
1007 test = 'line 1\nline 2\nline 3'
1008
1009 print "wrap 5-6-7 initial 0, subsequent 0"
1010 print wrap(test, 5)
1011 print
1012 print wrap(test, 6)
1013 print
1014 print wrap(test, 7)
1015 print "-------"
1016 raw_input()
1017 print "wrap 5 initial 1-1-3, subsequent 1-3-1"
1018 print wrap(test, 5, u' ', u' ')
1019 print
1020 print wrap(test, 5, u' ', u' ')
1021 print
1022 print wrap(test, 5, u' ', u' ')
1023 print "-------"
1024 raw_input()
1025 print "wrap 6 initial 1-1-3, subsequent 1-3-1"
1026 print wrap(test, 6, u' ', u' ')
1027 print
1028 print wrap(test, 6, u' ', u' ')
1029 print
1030 print wrap(test, 6, u' ', u' ')
1031 print "-------"
1032 raw_input()
1033 print "wrap 7 initial 1-1-3, subsequent 1-3-1"
1034 print wrap(test, 7, u' ', u' ')
1035 print
1036 print wrap(test, 7, u' ', u' ')
1037 print
1038 print wrap(test, 7, u' ', u' ')
1039
1041 print '%s: %s' % (sys.argv[2], file2md5(sys.argv[2]))
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055 test_input2int()
1056
1057
1058
1059
1060