0001 ### BITPIM 0002 ### 0003 ### Copyright (C) 2003-2005 Roger Binns <rogerb@rogerbinns.com> 0004 ### 0005 ### This program is free software; you can redistribute it and/or modify 0006 ### it under the terms of the BitPim license as detailed in the LICENSE file. 0007 ### 0008 ### $Id: prototypeslg.py 4633 2008-07-05 05:04:50Z djpham $ 0009 0010 import bpcalendar 0011 0012 import calendar 0013 import prototypes 0014 import re 0015 import time 0016 0017 class LGCALDATE(prototypes.UINTlsb): 0018 def __init__(self, *args, **kwargs): 0019 """A date/time as used in the LG calendar""" 0020 super(LGCALDATE,self).__init__(*args, **kwargs) 0021 self._valuedate=(0,0,0,0,0) # year month day hour minute 0022 0023 dict={'sizeinbytes': 4} 0024 dict.update(kwargs) 0025 0026 if self._ismostderived(LGCALDATE): 0027 self._update(args, dict) 0028 0029 def _update(self, args, kwargs): 0030 for k in 'constant', 'default', 'value': 0031 if kwargs.has_key(k): 0032 kwargs[k]=self._converttoint(kwargs[k]) 0033 if len(args)==0: 0034 pass 0035 elif len(args)==1: 0036 args=(self._converttoint(args[0]),) 0037 else: 0038 raise TypeError("expected (year,month,day,hour,minute) as arg") 0039 0040 super(LGCALDATE,self)._update(args, kwargs) # we want the args 0041 self._complainaboutunusedargs(LGCALDATE,kwargs) 0042 assert self._sizeinbytes==4 0043 0044 def getvalue(self): 0045 """Unpack 32 bit value into date/time 0046 0047 @rtype: tuple 0048 @return: (year, month, day, hour, minute) 0049 """ 0050 val=super(LGCALDATE,self).getvalue() 0051 min=val&0x3f # 6 bits 0052 val>>=6 0053 hour=val&0x1f # 5 bits (uses 24 hour clock) 0054 val>>=5 0055 day=val&0x1f # 5 bits 0056 val>>=5 0057 month=val&0xf # 4 bits 0058 val>>=4 0059 year=val&0xfff # 12 bits 0060 return (year, month, day, hour, min) 0061 0062 def _converttoint(self, date): 0063 assert len(date)==5 0064 year,month,day,hour,min=date 0065 if year>4095: 0066 year=4095 0067 val=year 0068 val<<=4 0069 val|=month 0070 val<<=5 0071 val|=day 0072 val<<=5 0073 val|=hour 0074 val<<=6 0075 val|=min 0076 return val 0077 0078 class LGCALREPEAT(prototypes.UINTlsb): 0079 def __init__(self, *args, **kwargs): 0080 """A 32-bit bitmapped value used to store repeat info for events in the LG calendar""" 0081 super(LGCALREPEAT,self).__init__(*args, **kwargs) 0082 0083 # The meaning of the bits in this field 0084 # MSB LSB 0085 # 3 2 1 0086 # 10987654321098765432109876543210 0087 # 210 repeat_type 0088 # 0 exceptions, set to 1 if there are exceptions 0089 # 6543210 dow_weekly (weekly repeat type) 0090 # 210 dow (monthly repeat type) 0091 # 543210 interval 0092 # 3210 month_index 0093 # 543210 day_index 0094 0095 # repeat_type: 0=none, 1=daily, 2=weekly, 3=monthly, 4=yearly, 5=weekdays, 6=XthDayEachMonth(e.g. 3rd Friday each month) 0096 # dow_weekly: Weekly repeat type only. Identical to bpcalender dow bits, multiple selections allowed(Bit0=sun,Bit1=mon,Bit2=tue,Bit3=wed,Bit4=thur,Bit5=fri,Bit6=sat) 0097 # dow_monthly: Monthly repeat type 6 only. (0=sun,1=mon,2=tue,3=wed,4=thur,5=fri,6=sat) 0098 # interval: repeat interval, eg. every 1 week, 2 weeks 4 weeks etc. Also be used for months, but bp does not support this. 0099 # month_index: For type 4 this is the month the event starts in 0100 # day_index: For type 6 this represents the number of the day that is the repeat, e.g. "2"nd tuesday 0101 # For type 3&4 this is the day of the month that the repeat occurs, usually the same as the start date. 0102 # bp does not support this not being the support date 0103 0104 dict={'sizeinbytes': 4} 0105 dict.update(kwargs) 0106 0107 if self._ismostderived(LGCALREPEAT): 0108 self._update(args, dict) 0109 0110 def _update(self, args, kwargs): 0111 for k in 'constant', 'default', 'value': 0112 if kwargs.has_key(k): 0113 kwargs[k]=self._converttoint(kwargs[k]) 0114 if len(args)==0: 0115 pass 0116 elif len(args)==1: 0117 args=(self._converttoint(args[0]),) 0118 else: 0119 raise TypeError("expected (type, dow, interval) as arg") 0120 0121 super(LGCALREPEAT,self)._update(args, kwargs) # we want the args 0122 self._complainaboutunusedargs(LGCALDATE,kwargs) 0123 assert self._sizeinbytes==4 0124 0125 def getvalue(self): 0126 val=super(LGCALREPEAT,self).getvalue() 0127 type=val&0x7 # 3 bits 0128 val>>=4 0129 exceptions=val&0x1 0130 val>>=1 0131 #get day of week, only valid for some repeat types 0132 #format of data is also different for different repeat types 0133 interval2=(val>>9)&0x3f 0134 if type==6: # for monthly repeats 0135 dow=self._to_bp_dow[val&7] #day of month, valid for monthly repeat types, need to convert to bitpim format 0136 elif type==2: #weekly 0137 dow=val&0x7f # 7 bits, already matched bpcalender format 0138 else: 0139 dow=0 0140 # get interval 0141 if type==6: 0142 val>>=20 0143 interval=val&0x1f # day_index 0144 else: 0145 val>>=9 0146 interval=val&0x3f 0147 return (type, dow, interval, interval2, exceptions) 0148 0149 _caldomvalues={ 0150 0x01: 0x0, #sun 0151 0x02: 0x1, #mon 0152 0x04: 0x2, #tue 0153 0x08: 0x3, #wed 0154 0x10: 0x4, #thur 0155 0x20: 0x5, #fri 0156 0x40: 0x6 #sat 0157 } 0158 _to_bp_dow={ 0159 0: 0x01, # Sun 0160 1: 0x02, # Mon 0161 2: 0x04, # Tue 0162 3: 0x08, # Wed 0163 4: 0x10, # Thu 0164 5: 0x20, # Fri 0165 6: 0x40, # Sat 0166 } 0167 0168 def _converttoint(self, repeat): 0169 if not isinstance(repeat, (tuple, list)): 0170 if __debug__: 0171 raise TypeError 0172 else: 0173 return 0 0174 if len(repeat)!=5: 0175 if __debug__: 0176 raise ValueError 0177 else: 0178 return 0 0179 type,dow,interval,interval2,exceptions=repeat 0180 val=0 0181 # construct bitmapped value for repeat 0182 # look for weekday type 0183 val=interval 0184 if type==6 or type==3: 0185 val<<=11 0186 val|=interval2 0187 if type==4: #yearly 0188 val<<=11 0189 val|=dow 0190 val<<=9 0191 if type==2: 0192 val|=dow 0193 elif type==6: 0194 if self._caldomvalues.has_key(dow): 0195 val|=self._caldomvalues[dow] 0196 else: 0197 # invalid day-of-week for monthly type, just bail 0198 return 0 0199 val<<=1 0200 val|=exceptions 0201 val<<=4 0202 val|=type 0203 return val 0204 0205 class GPSDATE(prototypes.UINTlsb): 0206 _time_t_ofs=calendar.timegm((1980, 1, 6, 0, 0, 0)) 0207 _counter=0 0208 def __init__(self, *args, **kwargs): 0209 """A date/time as used in the LG call history files, 0210 @keyword unique: (True/False, Optional) Ensure that each GSPDATE instance 0211 is unique. 0212 """ 0213 super(GPSDATE, self).__init__(*args, **kwargs) 0214 self._unique=False 0215 dict={'sizeinbytes': 4} 0216 dict.update(kwargs) 0217 0218 if self._ismostderived(GPSDATE): 0219 self._update(args, dict) 0220 0221 def _update(self, args, kwargs): 0222 self._consumekw(kwargs, ('unique',)) 0223 for k in 'constant', 'default', 'value': 0224 if kwargs.has_key(k): 0225 kwargs[k]=self._converttoint(kwargs[k]) 0226 0227 if len(args)==0: 0228 pass 0229 elif len(args)==1: 0230 args=(self._converttoint(args[0]),) 0231 else: 0232 raise TypeError("expected (year,month,day,hour,minute,sec) as arg") 0233 0234 super(GPSDATE, self)._update(args, kwargs) # we want the args 0235 self._complainaboutunusedargs(GPSDATE,kwargs) 0236 assert self._sizeinbytes==4 0237 0238 def getvalue(self): 0239 """Convert 32 bit value into date/time 0240 0241 @rtype: tuple 0242 @return: (year, month, day, hour, minute, sec) 0243 """ 0244 return time.gmtime(self._time_t_ofs+super(GPSDATE, self).getvalue())[:6] 0245 0246 def _converttoint(self, date): 0247 assert len(date)==6 0248 _val=calendar.timegm(date)-self._time_t_ofs 0249 if self._unique: 0250 _val+=GPSDATE._counter 0251 GPSDATE._counter+=1 0252 if GPSDATE._counter==0xffff: 0253 GPSDATE._counter=0 0254 return _val 0255 @classmethod 0256 def now(_): 0257 return time.gmtime()[:6] 0258 0259 class GSMCALDATE(prototypes.CSVSTRING): 0260 """ Represent date string with format "YYMMDD*" 0261 This format is being used in LG GSM Calendar Evetns 0262 """ 0263 def __init__(self, *args, **kwargs): 0264 super(GSMCALDATE, self).__init__(*args, **kwargs) 0265 self._data=None 0266 self._readmode=True 0267 if self._ismostderived(GSMCALDATE): 0268 self._update(args, kwargs) 0269 0270 def _set_data(self, v=None): 0271 if v: 0272 self._data=v[:3] 0273 else: 0274 self._data=(2000+int(self._value[:2]), int(self._value[2:4]), 0275 int(self._value[4:6])) 0276 def _set_value(self): 0277 self._value='%02d%02d%02d'%(self._data[0]-2000, self._data[1], 0278 self._data[2]) 0279 0280 def _update(self, args, kwargs): 0281 self._consumekw(kwargs, ('readmode',)) 0282 if len(args)==1: 0283 if isinstance(args[0], (list, tuple)): 0284 super(GSMCALDATE, self)._update((), kwargs) 0285 self._set_data(args[0]) 0286 self._set_value() 0287 elif isinstance(args[0], (str, unicode)): 0288 super(GSMCALDATE, self)._update(args, kwargs) 0289 self._set_data() 0290 else: 0291 raise TypeError 0292 elif len(args)==0: 0293 super(GSMCALDATE, self)._update(args, kwargs) 0294 else: 0295 raise TypeError 0296 self._complainaboutunusedargs(GSMCALDATE, kwargs) 0297 0298 def readfrombuffer(self, buf): 0299 super(GSMCALDATE, self).readfrombuffer(buf) 0300 if self._value: 0301 self._set_data() 0302 else: 0303 self._data=None 0304 0305 def getvalue(self): 0306 """Returns the tuple of (year, month, day)""" 0307 if self._data is None: 0308 if self._value is None: 0309 raise prototypes.ValueNotSetException() 0310 self._set_data() 0311 if self._readmode: 0312 return self._data 0313 else: 0314 if self._quotechar: 0315 _quote=chr(self._quotechar) 0316 else: 0317 _quote='' 0318 return _quote+self._value+_quote 0319 0320 class GSMCALTIME(GSMCALDATE): 0321 """ Represent date time with format "hhm" 0322 This format is being used in LG GSM Calendar Evetns 0323 """ 0324 0325 def __init__(self, *args, **kwargs): 0326 super(GSMCALTIME, self).__init__(*args, **kwargs) 0327 if self._ismostderived(GSMCALTIME): 0328 self._update(args, kwargs) 0329 0330 def _set_data(self, v=None): 0331 if v: 0332 self._data=v[:2] 0333 else: 0334 self._data=(int(self._value[:2]), int(self._value[2:4])) 0335 0336 def _set_value(self): 0337 self._value='%02d%02d'%self._data 0338 0339 class SMSDATETIME(prototypes.CSVSTRING): 0340 """ Represent date time with the format 'yy/MM/dd,hh:mm:ss+-zz' used 0341 by GSM SMS messages. 0342 Currently works only 1 way: SMS Date Time -> ISO String 0343 """ 0344 _re_pattern='^\d\d/\d\d/\d\d,\d\d:\d\d:\d\d[+\-]\d\d$' 0345 _re_compiled_pattern=None 0346 def __init__(self, *args, **kwargs): 0347 if SMSDATETIME._re_compiled_pattern is None: 0348 SMSDATETIME._re_compiled_pattern=re.compile(SMSDATETIME._re_pattern) 0349 super(SMSDATETIME, self).__init__(*args, **kwargs) 0350 if self._ismostderived(SMSDATETIME): 0351 self._update(args, kwargs) 0352 0353 def _update(self, args, kwargs): 0354 super(SMSDATETIME, self)._update(args, kwargs) 0355 if self._value and \ 0356 not re.match(SMSDATETIME._re_compiled_pattern, self._value): 0357 raise ValueError('COrrect Format: yy/MM/dd,hh:mm:ss+-zz') 0358 0359 def getvalue(self): 0360 """Returns the ISO Format 'YYYMMDDTHHMMSS+-mmss'""" 0361 if self._value: 0362 _s=self._value.split(',') 0363 return '20%sT%s00'%(_s[0].replace('/', ''), 0364 _s[1].replace(':', '')) 0365 0366 class TELUSLGCALREPEAT(prototypes.UINTlsb): 0367 def __init__(self, *args, **kwargs): 0368 """A 32-bit bitmapped value used to store repeat info for events in the LG calendar""" 0369 super(TELUSLGCALREPEAT,self).__init__(*args, **kwargs) 0370 0371 # The meaning of the bits in this field 0372 # MSB LSB 0373 # 3 2 1 0374 # 10987654321098765432109876543210 0375 # 210 repeat_type 0376 # 0 exceptions, set to 1 if there are exceptions 0377 # 6543210 dow_weekly (weekly repeat type) 0378 # 210 dow (monthly repeat type) 0379 # 543210 interval 0380 # 3210 month_index 0381 # 6543210 day_index 0382 0383 # repeat_type: 0=none, 1=daily, 2=weekdays, 3=weekly, 4=Month Nth Xday, 5=monthly on date, 6=yearly Nth Xday in month, 7=yearly on date 0384 # dow_weekly: Weekly repeat type only. Identical to bpcalender dow bits, multiple selections allowed(Bit0=sun,Bit1=mon,Bit2=tue,Bit3=wed,Bit4=thur,Bit5=fri,Bit6=sat) 0385 # dow_monthly: Monthly repeat type 6 only. (0=sun,1=mon,2=tue,3=wed,4=thur,5=fri,6=sat) 0386 # interval: repeat interval, eg. every 1 week, 2 weeks 4 weeks etc. Also be used for months, but bp does not support this. 0387 # month_index: For type 4 this is the month the event starts in 0388 # day_index: For type 6 this represents the number of the day that is the repeat, e.g. "2"nd tuesday 0389 # For type 3&4 this is the day of the month that the repeat occurs, usually the same as the start date. 0390 # For type 0&2 set to 0x7F 0391 # For type 1&3 set to 0 0392 0393 dict={'sizeinbytes': 4} 0394 dict.update(kwargs) 0395 0396 if self._ismostderived(TELUSLGCALREPEAT): 0397 self._update(args, dict) 0398 0399 def _update(self, args, kwargs): 0400 for k in 'constant', 'default', 'value': 0401 if kwargs.has_key(k): 0402 kwargs[k]=self._converttoint(kwargs[k]) 0403 if len(args)==0: 0404 pass 0405 elif len(args)==1: 0406 args=(self._converttoint(args[0]),) 0407 else: 0408 raise TypeError("expected (type, dow, interval) as arg") 0409 0410 super(TELUSLGCALREPEAT,self)._update(args, kwargs) # we want the args 0411 self._complainaboutunusedargs(TELUSLGCALREPEAT,kwargs) 0412 assert self._sizeinbytes==4 0413 0414 def getvalue(self): 0415 val=super(TELUSLGCALREPEAT,self).getvalue() 0416 type=val&0x7 # 3 bits 0417 val>>=4 0418 exceptions=val&0x1 0419 val>>=1 0420 #get day of week, only valid for some repeat types 0421 #format of data is also different for different repeat types 0422 interval2=(val>>9)&0x3f 0423 if type==4: # for monthly repeats 0424 dow=self._to_bp_dow[val&7] #day of month, valid for monthly repeat types, need to convert to bitpim format 0425 elif type==3: #weekly 0426 dow=val&0x7f # 7 bits, already matched bpcalender format 0427 else: 0428 dow=0 0429 # get interval 0430 if type==4: 0431 val>>=20 0432 interval=val&0x1f # day_index 0433 else: 0434 val>>=9 0435 interval=val&0x3f 0436 return (type, dow, interval, interval2, exceptions) 0437 0438 _caldomvalues={ 0439 0x01: 0x0, #sun 0440 0x02: 0x1, #mon 0441 0x04: 0x2, #tue 0442 0x08: 0x3, #wed 0443 0x10: 0x4, #thur 0444 0x20: 0x5, #fri 0445 0x40: 0x6 #sat 0446 } 0447 _to_bp_dow={ 0448 0: 0x01, # Sun 0449 1: 0x02, # Mon 0450 2: 0x04, # Tue 0451 3: 0x08, # Wed 0452 4: 0x10, # Thu 0453 5: 0x20, # Fri 0454 6: 0x40, # Sat 0455 } 0456 0457 def _converttoint(self, repeat): 0458 if not isinstance(repeat, (tuple, list)): 0459 if __debug__: 0460 raise TypeError 0461 else: 0462 return 0 0463 if len(repeat)!=5: 0464 if __debug__: 0465 raise ValueError 0466 else: 0467 return 0 0468 type,dow,interval,interval2,exceptions=repeat 0469 val=0 0470 # construct bitmapped value for repeat 0471 val=interval 0472 if type==0 or type==2: 0473 val=0x7F 0474 val<<=11 0475 val|=interval 0476 if type==4 or type==5: 0477 val<<=11 0478 val|=interval2 0479 if type==7: #yearly 0480 val<<=11 0481 val|=dow 0482 val<<=9 0483 if type==2: 0484 val|=dow 0485 elif type==4: 0486 val|=self._caldomvalues[dow] 0487 val<<=1 0488 val|=exceptions 0489 val<<=4 0490 val|=type 0491 return val 0492 0493 #------------------------------------------------------------------------------- 0494 class T9USERDBBLOCK(prototypes.BaseProtogenClass): 0495 """ 0496 Special class to handle data blocks within the LG T9 User Database file. 0497 Perhaps, the prototypes syntax should be enhanced to more gracefully 0498 handle cases like this! 0499 """ 0500 0501 # known types of this block 0502 FreeBlock_Type='Free Block' 0503 A0_Type='A0 Block' 0504 WordsList_Type='Words List' 0505 C_Type='C' 0506 Garbage_Type='Garbage' 0507 0508 def __init__(self, *args, **kwargs): 0509 super(T9USERDBBLOCK, self).__init__(*args, **kwargs) 0510 self._value=None 0511 self._type=None 0512 if self._ismostderived(T9USERDBBLOCK): 0513 self._update(args, kwargs) 0514 0515 def _update(self, args, kwargs): 0516 super(T9USERDBBLOCK, self)._update(args, kwargs) 0517 # we have no special keywords to process so complain away 0518 self._complainaboutunusedargs(T9USERDBBLOCK, kwargs) 0519 # Set our value if one was specified 0520 if len(args)==0: 0521 pass 0522 elif len(args)==1: 0523 self._set_value(args[0]) 0524 else: 0525 raise TypeError("Unexpected arguments "+`args`) 0526 0527 def _set_value(self, v): 0528 # set the value of this block 0529 # the value must be a dict having 2 keys: 'type' and 'value' 0530 if not isinstance(v, dict): 0531 raise TypeError('Value must be a dict') 0532 if not v.has_key('type') or not v.has_key('value'): 0533 raise ValueError('Missing type or value keyword') 0534 _type=v['type'] 0535 _value=v['value'] 0536 if _type==self.FreeBlock_Type: 0537 # this is a free block, the value is an integer specifying 0538 # the length of this free block 0539 if not isinstance(_value, int): 0540 raise TypeError('Value must be an int') 0541 elif _type==self.WordsList_Type: 0542 # this is a list of words, the value is a list of dicts, 0543 # each dict should have 2 keys: 'word', 'weight'. 0544 # value['word'] is a string 0545 # value['weight'] is an int, default to 0xA000 0546 if not isinstance(_value, list): 0547 raise TypeError('Value must be a list of dicts') 0548 elif _type==self.A0_Type: 0549 _value=0xA0 0550 else: 0551 raise ValueError('Invalid type: '+_type) 0552 self._type=_type 0553 self._value=_value 0554 0555 def _extract_words_list(self, buf): 0556 # read and construct a word list 0557 _res=[] 0558 _size=buf.peeknextbyte() 0559 while _size<0x80: 0560 _size=buf.getnextbyte() 0561 _weight=buf.getnextbyte()|(buf.getnextbyte()<<8) 0562 _res.append({ 'word': buf.getnextbytes(_size), 0563 'weight': _weight }) 0564 _size=buf.peeknextbyte() 0565 return _res 0566 def readfrombuffer(self, buf): 0567 try: 0568 self._bufferstartoffset=buf.getcurrentoffset() 0569 _ch=buf.peeknextbyte() 0570 if _ch&0xF0==0xC0: 0571 self._type=self.C_Type 0572 self._value='' 0573 while True: 0574 b=buf.getnextbytes(1) 0575 self._value+=b 0576 if b=='\x09': 0577 self._value+=buf.getnextbytes(1) 0578 break 0579 elif _ch&0xF0==0xA0: 0580 self._type=self.A0_Type 0581 self._value=buf.getnextbyte() 0582 elif _ch&0xF0==0x80: 0583 self._type=self.FreeBlock_Type 0584 self._value=((buf.getnextbyte()&0x0F)<<8)|buf.getnextbyte() 0585 buf.getnextbytes(self._value-2) 0586 elif _ch<0x80: 0587 self._type=self.WordsList_Type 0588 self._value=self._extract_words_list(buf) 0589 else: 0590 raise ValueError('Unknown block type: 0x%02X'%_ch) 0591 except IndexError: 0592 # ignore garbage at the end 0593 self._type=self.Garbage_Type 0594 self._value=0 0595 ## print 'type:',self._type 0596 ## print 'value:',self._value 0597 self._bufferendoffset=buf.getcurrentoffset() 0598 0599 def getvalue(self): 0600 if self._value is None or self._type is None: 0601 raise ValueNotSetException() 0602 return { 'type': self._type, 0603 'value': self._value } 0604 0605 def packetsize(self): 0606 # return the size of this packet 0607 if self._value is None or self._type is None: 0608 raise ValueNotSetException() 0609 if self._type==self.C_Type or \ 0610 self._type==self.A0_Type: 0611 return len(self._value) 0612 if self._type==self.FreeBlock_Type: 0613 return self._value 0614 if self._type==self.WordsList_Type: 0615 _size=0 0616 for _entry in self._value: 0617 _size+=len(_entry['word'])+3 0618 return _size 0619 0620 def writetobuffer(self, buf): 0621 if self._value is None or self._type is None: 0622 raise ValueNotSetException() 0623 self._bufferstartoffset=buf.getcurrentoffset() 0624 if self._type==self.C_Type: 0625 buf.appendbytes(self._value) 0626 elif self._type==self.A0_Type: 0627 buf.appendbyte(0xA0) 0628 elif self._type==self.FreeBlock_Type: 0629 buf.appendbyte(0x80|((self._value&0xF00)>>8)) 0630 buf.appendbyte(self._value&0xff) 0631 for _ in range(self._value-2): 0632 buf.appendbyte(0) 0633 elif self._type==self.WordsList_Type: 0634 for _entry in self._value: 0635 buf.appendbyte(len(_entry['word'])) 0636 _weight=_entry.get('weight', 0xA000) 0637 buf.appendbyte(_weight&0xff) 0638 buf.appendbyte((_weight&0xFF00)>>8) 0639 buf.appendbytes(_entry['word']) 0640 self._bufferendoffset=buf.getcurrentoffset() 0641 0642 class LGHEXPN(prototypes.DATA): 0643 """ Phone numbers stored as hex. i.e. 0x5555551212f0 == 555-555-1212 0644 """ 0645 def __init__(self, *args, **kwargs): 0646 """A date/time as used in the LG calendar""" 0647 super(LGHEXPN,self).__init__(*args, **kwargs) 0648 self._update(args, kwargs) 0649 0650 def _update (self, args, kwargs): 0651 for k in 'constant', 'default', 'value': 0652 if kwargs.has_key(k): 0653 kwargs[k]=self._string_to_lghexpn (kwargs[k]) 0654 if len(args)==0: 0655 pass 0656 elif len(args)==1: 0657 args = (self._string_to_lghexpn (args[0]),) 0658 else: 0659 raise TypeError("Expected phone number string as arg") 0660 0661 super(LGHEXPN,self)._update(args, kwargs) 0662 0663 def _digit_to_char (self, digit): 0664 if digit <= 0x09: 0665 return chr (digit + ord('0')) 0666 elif digit == 0x0A: 0667 return '*' 0668 elif digit == 0x0B: 0669 return '#' 0670 elif digit == 0x0C: 0671 return 'W' 0672 elif digit == 0x0D: 0673 return 'P' 0674 else: 0675 # 0x0f is not an error 0676 raise 0677 0678 def _char_to_digit (self, char): 0679 if char >= '0' and char <= '9': 0680 return ord(char) - ord('0') 0681 elif char == '*': 0682 return 0x0A 0683 elif char == '#': 0684 return 0x0B 0685 elif char == 'W': 0686 return 0x0C 0687 elif char == 'P': 0688 return 0x0D 0689 else: 0690 raise ValueError 0691 0692 def _string_to_lghexpn (self, pn): 0693 val = '' 0694 0695 byte = 0xf0 0696 for i in range(0, len (pn)): 0697 digit = self._char_to_digit (pn[i]) 0698 if i % 2: 0699 val += chr(byte & (0xf0 | digit)) 0700 byte = 0xf0 0701 else: 0702 byte = (digit << 4) | 0x0f 0703 # write terminating byte 0704 val += chr(byte) 0705 0706 return val 0707 0708 def getvalue(self): 0709 """Unpack hex phone number 0710 0711 @rtype: string 0712 @return: phone number 0713 """ 0714 val=super(LGHEXPN,self).getvalue() 0715 pn = '' 0716 for byte in val: 0717 fd = ord(byte) >> 4 0718 sd = ord(byte) & 0x0f 0719 0720 try: 0721 pn += self._digit_to_char(fd) 0722 pn += self._digit_to_char(sd) 0723 except: 0724 # end of packed number, not an error 0725 break 0726 return pn 0727 0728 class PBDateTime(prototypes.BaseProtogenClass): 0729 "Handle six 2-byte UINTs: y, m, d, h, m, s" 0730 0731 def __init__(self, *args, **kwargs): 0732 """ 0733 Class to handle the date/time format of 6 2-byte UINTs: y, m, d, h, m, s 0734 @keyword default: (Optional) Our default value 0735 @keyword defaulttocurrenttime: (Optional) Default to the current date/time 0736 """ 0737 super(PBDateTime, self).__init__(*args, **kwargs) 0738 self._default=None 0739 self._defaulttocurrenttime=False 0740 self._value=None 0741 0742 if self._ismostderived(PBDateTime): 0743 self._update(args, kwargs) 0744 0745 def _update(self, args, kwargs): 0746 super(PBDateTime, self)._update(args, kwargs) 0747 self._consumekw(kwargs, ("default", "defaulttocurrenttime", "value")) 0748 self._complainaboutunusedargs(PBDateTime, kwargs) 0749 0750 if len(args)==0: 0751 pass 0752 elif len(args)==1: 0753 self._value=args[0] 0754 else: 0755 raise TypeError("Unexpected arguments "+`args`) 0756 0757 if self._value is None: 0758 # value not specified, check for either default or default to 0759 # current time 0760 if self._default: 0761 self._value=self._default 0762 elif self._defaulttocurrenttime: 0763 self._value=time.localtime()[:6] 0764 0765 def readfrombuffer(self, buf): 0766 self._bufferstartoffset=buf.getcurrentoffset() 0767 0768 _res=[] 0769 for i in range(6): 0770 _res.append(buf.getnextbyte()|(buf.getnextbyte()<<8)) 0771 self._value=_res 0772 0773 self._bufferendoffset=buf.getcurrentoffset() 0774 0775 def writetobuffer(self, buf): 0776 if self._value is None: 0777 raise ValueNotSetException() 0778 if not isinstance(self._value, (list, tuple)): 0779 raise TypeError('value needs to be a list/tuple') 0780 if len(self._value)!=6: 0781 raise TypeError('len of value needs to be 6') 0782 0783 self._bufferstartoffset=buf.getcurrentoffset() 0784 for _num in self._value: 0785 buf.appendbyte(_num&0xff) 0786 buf.appendbyte((_num>>8)&0xff) 0787 self._bufferendoffset=buf.getcurrentoffset() 0788 0789 def packetsize(self): 0790 """Size in bytes""" 0791 return 12 0792 0793 def getvalue(self): 0794 if self._value is None: 0795 raise ValueNotSetException() 0796 return self._value 0797
Generated by PyXR 0.9.4