1
2
3
4
5
6
7
8
9
10
11
12 """Various classes and functions that are used by GUI and command line versions of BitPim"""
13
14 from __future__ import with_statement
15 from contextlib import contextmanager
16
17
18 import string
19 import cStringIO
20 import StringIO
21 import sys
22 import traceback
23 import tempfile
24 import random
25 import os
26 import imp
27 import unicodedata
30 """The device doesn't support the feature"""
31 - def __init__(self, device, message="The device doesn't support the feature"):
32 Exception.__init__(self, "%s: %s" % (device, message))
33 self.device=device
34 self.message=message
35
38 Exception.__init__(self, "%s: %s" % (device, message))
39 self.device=device
40 self.message=message
41
43 "The phonebook is busy on the phone"
44 pass
45
47 - def __init__(self, basename, fullname, paths):
48 Exception.__init__(self, "Helper binary %s not found. It should be in one of %s" % (fullname, ", ".join(paths)))
49 self.basename=basename
50 self.fullname=fullname
51 self.paths=paths
52
54 - def __init__(self, retcode, args, logstr=None):
55 Exception.__init__(self, "Command execution failed with code %d: %s" % (retcode, " ".join(args)))
56 self.retcode=retcode
57 self.args=args
58 self.logstr=logstr
59
64
67 Exception.__init__(self, "BitPim is in safe mode - this operation has been blocked")
68
71 """Generic commmunications exception"""
72 - def __init__(self, message, device="<>"):
73 Exception.__init__(self, "%s: %s" % (device, message))
74 self.device=device
75 self.message=message
76
78 """The communication settings need to be configured"""
79 pass
80
82 """The communication port or device attached to it needs some
83 manual intervention"""
84 pass
85
87 """There was some form of data corruption"""
88 pass
89
91 """Timeout while reading or writing the commport"""
92 pass
93
95 """Failed to open the communications port/device"""
96 pass
97
99 """The wrong port has been selected, typically the modem port on an LG composite device"""
100 pass
101
103 """Failed to auto detect a useful port"""
105 self.device="auto"
106 self.message="Failed to auto-detect the port to use. "
107 if portstried is not None and len(portstried):
108 self.message+="I tried "+", ".join(portstried)
109 else:
110 self.message+="I couldn't detect any candidate ports"
111 CommsException.__init__(self, self.message, self.device)
112
114 - def __init__(self, string=None, codec=None):
118
120 - def __init__(self, string=None, codec=None):
124
126 """Returns a pretty printed hexdump of the data
127
128 @rtype: string"""
129 res=cStringIO.StringIO()
130 lchar=""
131 lhex="00000000 "
132 for count in range(0, len(data)):
133 b=ord(data[count])
134 lhex=lhex+"%02x " % (b,)
135 if b>=32 and string.printable.find(chr(b))>=0:
136 lchar=lchar+chr(b)
137 else:
138 lchar=lchar+'.'
139
140 if (count+1)%16==0:
141 res.write(lhex+" "+lchar+"\n")
142 lhex="%08x " % (count+1,)
143 lchar=""
144 if len(data):
145 while (count+1)%16!=0:
146 count=count+1
147 lhex=lhex+" "
148 res.write(lhex+" "+lchar+"\n")
149 return res.getvalue()
150
152 "Turns binary data into a hex string (like the output of MD5/SHA hexdigest)"
153 return "".join(["%02x" % (ord(x),) for x in data])
154
156 """Returns a pretty printed version of the dictionary
157
158 The elements are sorted into alphabetical order, and printed
159 one per line. Dictionaries within the values are also pretty
160 printed suitably indented.
161
162 @rtype: string"""
163
164 res=cStringIO.StringIO()
165
166
167 istr=" "
168
169
170 res.write("%s{\n" % (istr*indent,))
171 indent+=1
172
173
174 keys=dictionary.keys()
175 keys.sort()
176
177
178 for k in keys:
179 v=dictionary[k]
180
181 if isinstance(v, dict):
182 res.write("%s%s:\n%s\n" % (istr*indent, `k`, prettyprintdict(v, indent+1)))
183 else:
184
185 if isinstance(v, list):
186 dicts=0
187 for item in v:
188 if isinstance(item, dict):
189 dicts+=1
190 if dicts and dicts==len(v):
191 res.write("%s%s:\n%s[\n" % (istr*indent,`k`,istr*(indent+1)))
192 for item in v:
193 res.write(prettyprintdict(item, indent+2))
194 res.write("%s],\n" % (istr*(indent+1)))
195 continue
196 res.write("%s%s: %s,\n" % (istr*indent, `k`, `v`))
197
198
199 indent-=1
200 if indent>0:
201 comma=","
202 else:
203 comma=""
204 res.write("%s}%s\n" % (istr*indent,comma))
205
206 return res.getvalue()
207
210 """A debugging assist class that helps in tracking down functions returning exceptions"""
212 self.callable=callable
213
215 try:
216
217 return self.callable(*args, **kwargs)
218 except:
219 print "in exception wrapped call", `self.callable`
220 print formatexception()
221 raise
222
224
225
226
227
228 curdir=os.getcwdu()
229 filepath, file=os.path.split(filename)
230 os.chdir(filepath)
231 if dict1==0:
232 execfile(file)
233 elif dict2==0:
234 execfile(file, dict1)
235 else:
236 execfile(file, dict1, dict2)
237 os.chdir(curdir)
238
240 assert currentversion>0
241 try:
242 execfile(filename, dict, dict)
243 except UnicodeError:
244 unicode_execfile(filename, dict, dict)
245 if not dict.has_key('FILEVERSION'):
246 version=0
247 else:
248 version=dict['FILEVERSION']
249 del dict['FILEVERSION']
250 if version<currentversion:
251 versionhandlerfunc(dict, version)
252
254 assert currentversion>0
255 with file(filename, 'w') as f:
256 for key in dict:
257 v=dict[key]
258 if isinstance(v, type({})):
259 f.write("result['%s']=%s\n" % (key, prettyprintdict(dict[key])))
260 else:
261 f.write("result['%s']=%s\n" % (key, `v`))
262 f.write("FILEVERSION=%d\n" % (currentversion,))
263
266
316
318 "Returns a filename to be used for a temporary file"
319
320 if extension:
321 x=tempfile.NamedTemporaryFile(suffix="."+extension)
322 else:
323 x=tempfile.NamedTemporaryFile()
324 n=x.name
325 x.close()
326 del x
327 return n
328
330 """Returns the object corresponding to name.
331 Imports will be done as necessary to resolve
332 every part of the name"""
333 mods=name.split('.')
334 dict={}
335 for i in range(len(mods)):
336
337 try:
338 exec "import %s" % (".".join(mods[:i])) in dict, dict
339 except:
340 pass
341
342 return eval(name, dict, dict)
343
345 res=[]
346 for l in lists:
347 for item in l:
348 if item not in res:
349 res.append(item)
350 return res
351
352 -def getkv(dict, key, updates=None):
353 "Gets a key and value from a dict, returning as a dict potentially applying updates"
354 d={key: dict[key].copy()}
355 if updates:
356 d[key].update(updates)
357 return d
358
359
360
361 _magic=[ord(x) for x in "IamAhaPp12&s]"]
369
378
379
380
381
382
383
384
385 import codecs
386
387 _boms=[]
388
389 try:
390 import encodings.utf_64
391 _boms.append( (codecs.BOM64_BE, "utf_64") )
392 _boms.append( (codecs.BOM64_LE, "utf_64") )
393 except: pass
394
395
396 try:
397 import encodings.utf_32
398 _boms.append( (codecs.BOM_UTF32, "utf_32") )
399 _boms.append( (codecs.BOM_UTF32_BE, "utf_32") )
400 _boms.append( (codecs.BOM_UTF32_LE, "utf_32") )
401 except: pass
402
403
404 try:
405 import encodings.utf_16
406 _boms.append( (codecs.BOM_UTF16, "utf_16") )
407 _boms.append( (codecs.BOM_UTF16_BE, "utf_16_be") )
408 _boms.append( (codecs.BOM_UTF16_LE, "utf_16_le") )
409 except: pass
410
411
412 try:
413 import encodings.utf_8
414 _boms.append( (codecs.BOM_UTF8, "utf_8") )
415 except: pass
416
417
418
419 _boms.append( ("\0B\0E\0G\0I\0N\0:\0V\0C\0A\0R\0D", "utf_16_be") )
420 _boms.append( ("B\0E\0G\0I\0N\0:\0V\0C\0A\0R\0D\0", "utf_16_le") )
421
422
423
424
425
426
427
428 _maxbomlen=max([len(bom) for bom,codec in _boms])
429
430 -def opentextfile(name):
431 """This function detects unicode byte order markers and if present
432 uses the codecs module instead to open the file instead with
433 appropriate unicode decoding, else returns the file using standard
434 open function"""
435 with file(name, 'rb') as f:
436 start=f.read(_maxbomlen)
437 for bom,codec in _boms:
438 if start.startswith(bom):
439
440
441
442 return StringIO.StringIO(codecs.open(name, "r", codec).read())
443 return file(name, "rtU")
444
445
446
447
448
449
450
451
452
453
454
455
456
457 -def forceascii(s):
459
460
461
462
463 pppterminator="\x7e"
468
470 if d.find("\x7d")<0: return d
471 res=list(d)
472 try:
473 start=0
474 while True:
475 p=res.index("\x7d", start)
476 res[p:p+2]=chr(ord(res[p+1])^0x20)
477 start=p+1
478 except ValueError:
479 return "".join(res)
480
481
482
483 _crctable=(
484 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
485 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
486 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
487 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
488 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
489 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
490 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
491 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
492 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
493 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
494 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
495 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
496 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
497 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
498 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
499 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
500 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
501 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
502 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
503 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
504 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
505 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
506 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
507 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
508 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
509 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
510 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
511 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
512 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
513 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
514 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
515 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78,
516 )
517
518 -def crc(data, initial=0xffff):
519 "CRC calculation - returns 16 bit integer"
520 res=initial
521 for byte in data:
522 curres=res
523 res=res>>8
524 val=(ord(byte)^curres) & 0xff
525 val=_crctable[val]
526 res=res^val
527
528 res=(~res)&0xffff
529 return res
530
531 -def crcs(data, initial=0xffff):
532 "CRC calculation - returns 2 byte string LSB"
533 r=crc(data, initial)
534 return "%c%c" % ( r& 0xff, (r>>8)&0xff)
535
536
537
538
539
540
541
542 -def basename(name):
547
553
558
560 if name.rfind('.')>=0:
561 return name[name.rfind('.')+1:]
562 return ''
563
568 if len(v)<2:
569 return None
570 return ord(v[0])+(ord(v[1])<<8)
571
573 if len(v)<4:
574 return None
575 return ord(v[0])+(ord(v[1])<<8)+(ord(v[2])<<16)+(ord(v[3])<<24)
576
578 if len(v)<2:
579 return None
580 return ord(v[1])+(ord(v[0])<<8)
581
583 if len(v)<4:
584 return None
585 return ord(v[3])+(ord(v[2])<<8)+(ord(v[1])<<16)+(ord(v[0])<<24)
586
588 return chr(v&0xff)+chr((v>>8)&0xff)
589
591 return chr(v&0xff)+chr((v>>8)&0xff)+chr((v>>16)&0xff)+chr((v>>24)&0xff)
592
594 return chr((v>>8)&0xff)+chr(v&0xff)
595
597 return chr((v>>24)&0xff)+chr((v>>16)&0xff)+chr((v>>8)&0xff)+chr(v&0xff)
598
599
600
601
602
603
604 nibbles=("0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111")
608
610 res=0
611 for i in v:
612 res*=2
613 res+=bool(i=="1")
614 return res
615
620 """Decodes the characters out of a string of bytes where each
621 character takes a fixed number of bits (eg 7)
622
623 @param bytes: atring containing the raw bytes
624 @param bitsperchar: number of bits making up each character
625 @param charconv: the function used to convert the integer value
626 into a character
627 @param terminator: if this character is seen then it and the remaining bits are ignored"""
628 bits="".join([tobinary(ord(c)) for c in bytes])
629 value=[]
630 while len(bits):
631 c=charconv(frombinary(bits[:bitsperchar]))
632 if c==terminator:
633 break
634 value.append(c)
635 bits=bits[bitsperchar:]
636 return "".join(value)
637
640
641 temp_str=''
642 if uni_string is None:
643 return temp_str
644 try:
645 temp_str=uni_string.encode(codec)
646 return temp_str
647 except UnicodeError:
648 pass
649
650 temp_str=''
651 if codec=='ascii':
652 temp_str=get_ascii_string(uni_string, error_handling)
653 else:
654
655
656
657 for i in range(len(uni_string)):
658 try:
659 temp_char=uni_string[i].encode(codec)
660 except UnicodeError:
661 temp_char=get_ascii_string(uni_string[i], error_handling)
662 temp_str+=temp_char
663 return temp_str
664
666 "converts any type into an ascii byte string, for unicode string it will degrade if possible"
667 if uni_string is None:
668 return None
669 if not isinstance(uni_string, (str, unicode)):
670
671 return str(uni_string)
672 if not isinstance(uni_string, unicode):
673
674 return uni_string
675
676
677 kd_str=unicodedata.normalize('NFKD', uni_string)
678 stripped_str=u''
679
680
681 replace_chars= {
682 u"\N{COMBINING GRAVE ACCENT}": u"",
683 u"\N{COMBINING ACUTE ACCENT}": u"",
684 u"\N{COMBINING CIRCUMFLEX ACCENT}": u"",
685 u"\N{COMBINING TILDE}": u"",
686 u"\N{COMBINING MACRON}": u"",
687 u"\N{COMBINING OVERLINE}": u"",
688 u"\N{COMBINING BREVE}": u"",
689 u"\N{COMBINING DOT ABOVE}": u"",
690 u"\N{COMBINING DIAERESIS}": u"",
691 u"\N{COMBINING HOOK ABOVE}": u"",
692 u"\N{COMBINING RING ABOVE}": u"",
693 u"\N{COMBINING DOUBLE ACUTE ACCENT}": u"",
694 u"\N{COMBINING CARON}": u"",
695 u"\N{COMBINING VERTICAL LINE ABOVE}": u"",
696 u"\N{COMBINING DOUBLE VERTICAL LINE ABOVE}": u"",
697 u"\N{COMBINING DOUBLE GRAVE ACCENT}": u"",
698 u"\N{COMBINING CANDRABINDU}": u"",
699 u"\N{COMBINING INVERTED BREVE}": u"",
700 u"\N{COMBINING TURNED COMMA ABOVE}": u"",
701 u"\N{COMBINING COMMA ABOVE}": u"",
702 u"\N{COMBINING REVERSED COMMA ABOVE}": u"",
703 u"\N{COMBINING COMMA ABOVE RIGHT}": u"",
704 u"\N{COMBINING GRAVE ACCENT BELOW}": u"",
705 u"\N{COMBINING ACUTE ACCENT BELOW}": u"",
706 u"\N{COMBINING LEFT TACK BELOW}": u"",
707 u"\N{COMBINING RIGHT TACK BELOW}": u"",
708 u"\N{COMBINING LEFT ANGLE ABOVE}": u"",
709 u"\N{COMBINING HORN}": u"",
710 u"\N{COMBINING LEFT HALF RING BELOW}": u"",
711 u"\N{COMBINING UP TACK BELOW}": u"",
712 u"\N{COMBINING DOWN TACK BELOW}": u"",
713 u"\N{COMBINING PLUS SIGN BELOW}": u"",
714 u"\N{COMBINING MINUS SIGN BELOW}": u"",
715 u"\N{COMBINING PALATALIZED HOOK BELOW}": u"",
716 u"\N{COMBINING RETROFLEX HOOK BELOW}": u"",
717 u"\N{COMBINING DOT BELOW}": u"",
718 u"\N{COMBINING DIAERESIS BELOW}": u"",
719 u"\N{COMBINING RING BELOW}": u"",
720 u"\N{COMBINING COMMA BELOW}": u"",
721 u"\N{COMBINING CEDILLA}": u"",
722 u"\N{COMBINING OGONEK}": u"",
723 u"\N{COMBINING VERTICAL LINE BELOW}": u"",
724 u"\N{COMBINING BRIDGE BELOW}": u"",
725 u"\N{COMBINING INVERTED DOUBLE ARCH BELOW}": u"",
726 u"\N{COMBINING CARON BELOW}": u"",
727 u"\N{COMBINING CIRCUMFLEX ACCENT BELOW}": u"",
728 u"\N{COMBINING BREVE BELOW}": u"",
729 u"\N{COMBINING INVERTED BREVE BELOW}": u"",
730 u"\N{COMBINING TILDE BELOW}": u"",
731 u"\N{COMBINING MACRON BELOW}": u"",
732 u"\N{COMBINING LOW LINE}": u"",
733 u"\N{COMBINING DOUBLE LOW LINE}": u"",
734 u"\N{COMBINING TILDE OVERLAY}": u"",
735 u"\N{COMBINING SHORT STROKE OVERLAY}": u"",
736 u"\N{COMBINING LONG STROKE OVERLAY}": u"",
737 u"\N{COMBINING SHORT SOLIDUS OVERLAY}": u"",
738 u"\N{COMBINING LONG SOLIDUS OVERLAY}": u"",
739 u"\N{COMBINING RIGHT HALF RING BELOW}": u"",
740 u"\N{COMBINING INVERTED BRIDGE BELOW}": u"",
741 u"\N{COMBINING SQUARE BELOW}": u"",
742 u"\N{COMBINING SEAGULL BELOW}": u"",
743 u"\N{COMBINING X ABOVE}": u"",
744 u"\N{COMBINING VERTICAL TILDE}": u"",
745 u"\N{COMBINING DOUBLE OVERLINE}": u"",
746 u"\N{COMBINING GRAVE TONE MARK}": u"",
747 u"\N{COMBINING ACUTE TONE MARK}": u"",
748 u"\N{COMBINING GREEK PERISPOMENI}": u"",
749 u"\N{COMBINING GREEK KORONIS}": u"",
750 u"\N{COMBINING GREEK DIALYTIKA TONOS}": u"",
751 u"\N{COMBINING GREEK YPOGEGRAMMENI}": u"",
752 u"\N{COMBINING BRIDGE ABOVE}": u"",
753 u"\N{COMBINING EQUALS SIGN BELOW}": u"",
754 u"\N{COMBINING DOUBLE VERTICAL LINE BELOW}": u"",
755 u"\N{COMBINING LEFT ANGLE BELOW}": u"",
756 u"\N{COMBINING NOT TILDE ABOVE}": u"",
757 u"\N{COMBINING HOMOTHETIC ABOVE}": u"",
758 u"\N{COMBINING ALMOST EQUAL TO ABOVE}": u"",
759 u"\N{COMBINING LEFT RIGHT ARROW BELOW}": u"",
760 u"\N{COMBINING UPWARDS ARROW BELOW}": u"",
761 u"\N{COMBINING GRAPHEME JOINER}": u"",
762 u'\N{BROKEN BAR}': '|',
763 u'\N{CENT SIGN}': 'c',
764 u'\N{COPYRIGHT SIGN}': '(C)',
765 u'\N{DIVISION SIGN}': '/',
766 u'\N{INVERTED EXCLAMATION MARK}': '!',
767 u'\N{INVERTED QUESTION MARK}': '?',
768 u'\N{LATIN CAPITAL LETTER AE}': 'Ae',
769 u'\N{LATIN CAPITAL LETTER ETH}': 'Th',
770 u'\N{LATIN CAPITAL LETTER THORN}': 'Th',
771 u'\N{LATIN SMALL LETTER AE}': 'ae',
772 u'\N{LATIN SMALL LETTER ETH}': 'th',
773 u'\N{LATIN SMALL LETTER SHARP S}': 'ss',
774 u'\N{LATIN SMALL LETTER THORN}': 'th',
775 u'\N{LEFT-POINTING DOUBLE ANGLE QUOTATION MARK}': '<<',
776 u'\N{MIDDLE DOT}': '*',
777 u'\N{MULTIPLICATION SIGN}': '*',
778 u'\N{PLUS-MINUS SIGN}': '+/-',
779 u'\N{REGISTERED SIGN}': '(R)',
780 u'\N{RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK}': '>>',
781 u'\N{SOFT HYPHEN}': '-',
782 u'\N{VULGAR FRACTION ONE HALF}': '1/2',
783 u'\N{VULGAR FRACTION ONE QUARTER}': '1/4',
784 u'\N{VULGAR FRACTION THREE QUARTERS}': '3/4',
785 }
786 for i in range(len(kd_str)):
787 if kd_str[i] in replace_chars:
788 stripped_str+=replace_chars[kd_str[i]]
789 else:
790 stripped_str+=kd_str[i]
791
792
793 temp_str=stripped_str.encode('ascii', error_handling)
794 return temp_str
795
801 """Returns a simplified version of os.stat results that can be used to tell if a file
802 has changed. The normal structure returned also has things like last access time
803 which should not be used to tell if a file has changed."""
804 try:
805 s=os.stat(filename)
806 return (s.st_mode, s.st_ino, s.st_dev, s.st_uid, s.st_gid, s.st_size, s.st_mtime,
807 s.st_ctime)
808 except:
809 return None
810
812
813 - def __init__(self, lowwater=100, hiwater=140):
814 self.items={}
815 self.hiwater=hiwater
816 self.lowwater=lowwater
817
818 - def get(self, filename):
826
827 - def set(self, filename, value):
836
839 return __import__(name, globals(), locals(),
840 [name.split('.')[-1]])
841
842
843 -def main_is_frozen():
844 """ Return T if running from an exe, F otherwise
845 """
846 return (hasattr(sys, "frozen")
847 or hasattr(sys, "importers")
848 or imp.is_frozen("__main__")
849 or os.path.isfile(sys.path[0]))
850
852 """Return the absoluate path of the main BitPim dir
853 """
854 if main_is_frozen():
855 if sys.platform!='win32':
856 p=sys.path[0]
857 if os.path.isfile(p):
858 p=os.path.dirname(p)
859 return p
860
861 return os.path.abspath(os.path.dirname(sys.executable))
862
863 return os.path.split(os.path.abspath(os.path.dirname(sys.argv[0])))[0]
864
865 if sys.platform=='win32':
866
867 from win32api import GetFileVersionInfo, LOWORD, HIWORD
868 - def get_version_number (filename):
869 """Return the version of a Windows DLL or EXE file
870 """
871 try:
872 info = GetFileVersionInfo (filename, "\\")
873 ms = info['FileVersionMS']
874 ls = info['FileVersionLS']
875 return HIWORD (ms), LOWORD (ms), HIWORD (ls), LOWORD (ls)
876 except:
877 return None
878
882 _name=gettempfilename(ext)
883 try:
884 yield _name
885 finally:
886 try:
887 os.remove(_name)
888 except OSError:
889
890 pass
891