Changeset 1807
- Timestamp:
- 02/24/07 06:31:43 (22 months ago)
- Files:
-
- 1 modified
-
plugins/moto-sync/motosync.py (modified) (26 diffs)
Legend:
- Unmodified
- Added
- Removed
-
plugins/moto-sync/motosync.py
r1797 r1807 166 166 # logical order of the fields in structured XML data 167 167 XML_NAME_PARTS = 'Prefix FirstName Additional LastName Suffix'.split() 168 XML_ADDRESS_PARTS = ('Street ExtendedAddress' 169 + ' Locality Region PostalCode Country').split() 168 XML_ADDRESS_PARTS = ('Street ExtendedAddress Locality Region PostalCode Country').split() 170 169 171 170 # legal characters in telephone numbers … … 189 188 """Like DOM's getElementsByTagName, but allow multiple tag names.""" 190 189 for node in parent.childNodes: 191 if (node.nodeType == xml.dom.minidom.Node.ELEMENT_NODE 192 and node.tagName in tagnames): 190 if (node.nodeType == xml.dom.minidom.Node.ELEMENT_NODE and node.tagName in tagnames): 193 191 ret.append(node) 194 192 getElementsByTagNames(node, tagnames, ret) … … 241 239 DATETIME_PART = '(?:%s)?(?:%s)?' % (DATE_PART, TIME_PART) 242 240 WEEKS_PART = r'(\d+)W' 243 DURATION_REGEX = re.compile(r'([-+]?)P(?:%s|%s)$' 244 % (WEEKS_PART, DATETIME_PART)) 241 DURATION_REGEX = re.compile(r'([-+]?)P(?:%s|%s)$' % (WEEKS_PART, DATETIME_PART)) 245 242 246 243 def parse_ical_duration(duratstr): … … 444 441 # search for the port to use on the device 445 442 port = BT_DEFAULT_CHANNEL 446 found = bluetooth.find_service(name=BT_SERVICE_NAME, 447 address=self.devstr) 443 found = bluetooth.find_service(name=BT_SERVICE_NAME, address=self.devstr) 448 444 if found: 449 445 assert(found[0]['protocol'] == 'RFCOMM') … … 562 558 for (expos, exnum, extype) in self.__parse_results('MDBRE', data): 563 559 if extype != 1: # haven't seen anything else 564 raise opensync.Error('unexpected exception type %d' %extype)560 raise opensync.Error('unexpected exception type %d' % extype) 565 561 if not exceptions.has_key(expos): 566 562 exceptions[expos] = [] … … 691 687 debug('<-- ' + ret) 692 688 if c == '': # EOF, shouldn't happen 693 raise opensync.Error('Unexpected EOF talking to phone', 694 opensync.ERROR_IO_ERROR) 689 raise opensync.Error('Unexpected EOF talking to phone', opensync.ERROR_IO_ERROR) 695 690 return ret 696 691 … … 718 713 return ret 719 714 else: 720 raise opensync.Error("Error in phone command '%s'" % cmd, 721 opensync.ERROR_IO_ERROR) 715 raise opensync.Error("Error in phone command '%s'" % cmd, opensync.ERROR_IO_ERROR) 722 716 723 717 def __parse_results(self, restype, lines): … … 779 773 return '%d' 780 774 else: 781 assert(t == types.StringType or t == types.UnicodeType, 782 'unexpected type %s' % str(t)) 775 assert(t == types.StringType or t == types.UnicodeType, 'unexpected type %s' % str(t)) 783 776 return '"%s"' 784 777 … … 1002 995 e.setAttribute('DateValue', 'DATE') 1003 996 for exnum in self.exceptions: 1004 appendXMLChild(doc, e, 'Content', 1005 format_time(rrule[exnum], VCAL_DATE)) 997 appendXMLChild(doc, e, 'Content', format_time(rrule[exnum], VCAL_DATE)) 1006 998 if e.hasChildNodes(): 1007 999 top.appendChild(e) … … 1066 1058 if event.getElementsByTagName('Duration') != []: 1067 1059 duration = event.getElementsByTagName('Duration')[0] 1068 def tryint(s): 1069 if s == '': 1060 def toint(numstr): 1061 """Convert a string to an integer, unless it's empty, in which case return 0.""" 1062 if numstr == '': 1070 1063 return 0 1071 1064 else: 1072 return int( s)1073 weeks = t ryint(getXMLField(duration, 'Weeks'))1074 days = t ryint(getXMLField(duration, 'Days'))1075 hours = t ryint(getXMLField(duration, 'Hours'))1076 mins = t ryint(getXMLField(duration, 'Minutes'))1077 secs = t ryint(getXMLField(duration, 'Seconds'))1078 self.duration = datetime.timedelta(weeks * 7 + days, (hours * 60 + mins) * 60 + secs)1065 return int(numstr) 1066 weeks = toint(getXMLField(duration, 'Weeks')) 1067 days = toint(getXMLField(duration, 'Days')) 1068 hours = toint(getXMLField(duration, 'Hours')) 1069 mins = toint(getXMLField(duration, 'Minutes')) 1070 secs = toint(getXMLField(duration, 'Seconds')) 1071 self.duration = timedelta(weeks * 7 + days, (hours * 60 + mins) * 60 + secs) 1079 1072 else: 1080 1073 endstr = getField('DateEnd') … … 1108 1101 exdates = event.getElementsByTagName('ExceptionDateTime') 1109 1102 exrules = event.getElementsByTagName('ExceptionRule') 1110 (self.repeat_type, self.exceptions) = convert_rrule(rrules, exdates, 1111 exrules, self.eventdt) 1103 (self.repeat_type, self.exceptions) = convert_rrule(rrules, exdates, exrules, self.eventdt) 1112 1104 1113 1105 if len(rrules) > 0 and self.repeat_type == MOTO_REPEAT_NONE: … … 1474 1466 elif self.contacttype == MOTO_CONTACT_MAILINGLIST: 1475 1467 # the 'contact' is a space-separated list of other contact positions 1476 assert(False, "mailing lists aren't handled yet, sorry") # FIXME 1468 assert(False, "mailing lists aren't handled yet, sorry") # FIXME: implement mailing lists 1477 1469 else: 1478 1470 e = doc.createElement('Telephone') … … 1492 1484 if e.hasChildNodes(): 1493 1485 if MOTO_ADDRESS_TYPES.has_key(self.contacttype): 1494 e.setAttribute('Location', 1495 MOTO_ADDRESS_TYPES[self.contacttype].upper()) 1486 e.setAttribute('Location', MOTO_ADDRESS_TYPES[self.contacttype].upper()) 1496 1487 ret.append(e) 1497 1488 … … 1581 1572 for (bit, desc) in REQUIRED_FEATURES: 1582 1573 if not features[bit]: 1583 raise opensync.Error(desc + ' feature not present', 1584 opensync.ERROR_NOT_SUPPORTED) 1574 raise opensync.Error(desc + ' feature not present', opensync.ERROR_NOT_SUPPORTED) 1585 1575 1586 1576 # read current time on the phone, check if it matches our local time … … 1595 1585 1596 1586 # initialise the position allocators 1597 self.positions['event'] = PosAllocator('event', 0, 1598 self.comms.max_events - 1) 1587 self.positions['event'] = PosAllocator('event', 0, self.comms.max_events - 1) 1599 1588 min_contact = max(self.comms.min_contact_pos, MOTO_QUICKDIAL_ENTRIES) 1600 self.positions['contact'] = PosAllocator('contact', min_contact, 1601 self.comms.max_contact_pos) 1589 self.positions['contact'] = PosAllocator('contact', min_contact, self.comms.max_contact_pos) 1602 1590 1603 1591 # initialise the category mappings … … 1632 1620 else: 1633 1621 xmldata = entry.to_xml() 1634 print xmldata1635 1622 data = opensync.Data(xmldata, self.objformats[objtype]) 1636 1623 data.objtype = objtype … … 1663 1650 """ 1664 1651 objtype = change.objtype 1665 if change.objformat != self.objformats[objtype]: 1666 raise opensync.Error("unhandled data format "+change.objformat.name, 1667 opensync.ERROR_NOT_SUPPORTED) 1652 if change.objformat.name != self.objformats[objtype].name: 1653 raise opensync.Error("unhandled data format " + change.objformat.name, opensync.ERROR_NOT_SUPPORTED) 1668 1654 try: 1669 1655 if objtype == 'event': … … 1676 1662 # if its modified and we've seen it before, delete it 1677 1663 # otherwise just ignore it 1678 if (change.changetype == opensync.CHANGE_TYPE_MODIFIED 1679 and self.uid_seen(change.uid)): 1664 if (change.changetype == opensync.CHANGE_TYPE_MODIFIED and self.uid_seen(change.uid)): 1680 1665 change.changetype = opensync.CHANGE_TYPE_DELETED 1681 1666 change.data = None … … 1683 1668 else: 1684 1669 return False 1685 1686 1670 if change.changetype == opensync.CHANGE_TYPE_ADDED: 1687 1671 # allocate positions for the new entry … … 1705 1689 self.positions[objtype].mark_free(free_positions) 1706 1690 entry.set_pos(positions) 1707 1708 1691 entry.write(self.comms) 1709 1692 change.uid = self.__generate_uid(entry) … … 1740 1723 Uses the last 8 digit's of the phone's IMEI to do so. 1741 1724 """ 1742 return ("moto-%s-%s@%s" 1743 % (entry.get_objtype(), entry.generate_uid(), self.serial[-8:])) 1725 return ("moto-%s-%s@%s" % (entry.get_objtype(), entry.generate_uid(), self.serial[-8:])) 1744 1726 1745 1727 def __uid_to_pos(self, uid): … … 1749 1731 """ 1750 1732 moto, objtype, lastpart = uid.split('-', 2) 1751 assert(moto == "moto" and objtype in SUPPORTED_OBJTYPES, 1752 'Invalid UID: %s' % uid) 1733 assert(moto == "moto" and objtype in SUPPORTED_OBJTYPES, 'Invalid UID: %s' % uid) 1753 1734 lastpos = lastpart.rindex('@') 1754 assert(lastpart[lastpos + 1:] == self.serial[-8:], 1755 'Entry not created on this phone') 1735 assert(lastpart[lastpos + 1:] == self.serial[-8:], 'Entry not created on this phone') 1756 1736 1757 1737 if objtype == "event": … … 1783 1763 for change in self.access.list_changes(self.objtype): 1784 1764 self.hashtable.report(change.uid) 1785 change.changetype = self.hashtable.get_changetype(change.uid, 1786 change.hash) 1765 change.changetype = self.hashtable.get_changetype(change.uid, change.hash) 1787 1766 if change.changetype != opensync.CHANGE_TYPE_UNMODIFIED: 1788 self.hashtable.update_hash(change.changetype, change.uid, 1789 change.hash) 1767 self.hashtable.update_hash(change.changetype, change.uid, change.hash) 1790 1768 ctx.report_change(change) 1791 1769 for uid in self.hashtable.get_deleted(): … … 1799 1777 """Write a change to the phone.""" 1800 1778 if change.objtype != self.objtype: 1801 raise opensync.Error('unsupported objtype %s' % change.objtype, 1802 opensync.ERROR_NOT_SUPPORTED) 1803 if change.changetype != opensync.CHANGE_TYPE_DELETED: 1804 print "\nOpenSync wants me to write:\n", change.data.data 1779 raise opensync.Error('unsupported objtype %s' % change.objtype, opensync.ERROR_NOT_SUPPORTED) 1805 1780 if change.changetype == opensync.CHANGE_TYPE_DELETED: 1806 success = (self.access.uid_seen(change.uid) 1807 and self.access.delete_entry(change.uid)) 1781 success = (self.access.uid_seen(change.uid) and self.access.delete_entry(change.uid)) 1808 1782 elif change.changetype == opensync.CHANGE_TYPE_MODIFIED: 1809 1783 old_uid = change.uid … … 1812 1786 # the old one was deleted, to keep it consistent 1813 1787 if (success and old_uid != change.uid): 1814 self.hashtable.update_hash(opensync.CHANGE_TYPE_DELETED, 1815 old_uid, None) 1788 self.hashtable.update_hash(opensync.CHANGE_TYPE_DELETED, old_uid, None) 1816 1789 else: 1817 1790 success = self.access.update_entry(change) 1818 1791 if success: 1819 self.hashtable.update_hash(change.changetype, change.uid, 1820 change.hash) 1792 self.hashtable.update_hash(change.changetype, change.uid, change.hash) 1821 1793 1822 1794 def disconnect(self, info, ctx): … … 1830 1802 doc = xml.dom.minidom.parseString(configstr) 1831 1803 except: 1832 raise opensync.Error('failed to parse config data', 1833 opensync.ERROR_MISCONFIGURATION) 1804 raise opensync.Error('failed to parse config data', opensync.ERROR_MISCONFIGURATION) 1834 1805 1835 1806 ret = getXMLField(doc, 'device').strip() 1836 1807 if ret == '': 1837 raise opensync.Error('device not specified in config file', 1838 opensync.ERROR_MISCONFIGURATION) 1808 raise opensync.Error('device not specified in config file', opensync.ERROR_MISCONFIGURATION) 1839 1809 return ret 1840 1810
