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