Package modules :: Module calendar_syncml
[hide private]
[frames] | no frames]

Source Code for Module modules.calendar_syncml

  1  """  
  2  Syncronize with SyncML (Calendar) 
  3   
  4  This file is part of Pisi. This implementation is based on the Conduit branch of John Carr (http://git.gnome.org/cgit/conduit/log/?h=syncml), 
  5  which was one of the very first Python Syncml implementation - based on a ctime binding to the libsyncml library (https://libsyncml.opensync.org/). 
  6  The bindings were kept as found there - but I changed a lot the SyncModule file - in order to keep it as simple as possible. 
  7  Go and check L{thirdparty.conduit.SyncmlModule} for some more details. 
  8   
  9  Pisi is free software: you can redistribute it and/or modify 
 10  it under the terms of the GNU General Public License as published by 
 11  the Free Software Foundation, either version 3 of the License, or 
 12  (at your option) any later version. 
 13   
 14  Pisi is distributed in the hope that it will be useful, 
 15  but WITHOUT ANY WARRANTY; without even the implied warranty of 
 16  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 17  GNU General Public License for more details. 
 18   
 19  You should have received a copy of the GNU General Public License 
 20  along with Pisi.  If not, see <http://www.gnu.org/licenses/> 
 21   
 22  """ 
 23   
 24  import os.path 
 25  import sys,os,re 
 26  import vobject 
 27   
 28  # Allows us to import contact 
 29  sys.path.insert(0,os.path.abspath(__file__+"/../..")) 
 30  from events import events 
 31  from pisiconstants import * 
 32  import vobjecttools 
 33  import pisiprogress 
 34  import thirdparty.conduit.SyncmlModule as SyncmlModule 
 35   
 36  SYNCMLSERVER_IDENTIFIER = "pisi" 
 37  """What app name to use when connecting to Syncml server""" 
 38   
39 -class SynchronizationModule(events.AbstractCalendarSynchronizationModule):
40 """ 41 The implementation of the interface L{events.AbstractCalendarSynchronizationModule} for the Syncml Calendar backend 42 """
43 - def __init__( self, modulesString, config, configsection, folder, verbose=False, soft=False):
44 """ 45 Constructor 46 47 Super class constructor (L{events.AbstractCalendarSynchronizationModule.__init__}) is called. 48 Local variables are initialized. 49 The settings from the configuration file are loaded. 50 The connection to the Google Gdata backend is established. 51 """ 52 events.AbstractCalendarSynchronizationModule.__init__(self, verbose, soft, modulesString, config, configsection, "Syncml Calendar") 53 pisiprogress.getCallback().verbose('calendar syncml module loaded') 54 self._url = config.get(configsection,'url') 55 self._username = config.get(configsection,'username') 56 self._password = config.get(configsection,'password') 57 self._database = config.get(configsection,'database') 58 self._mapping = {}
59
60 - def load(self):
61 """ 62 Load all data from backend 63 64 For data parsing (VCF) the tools layer in L{vobjecttools} is used. 65 """ 66 pisiprogress.getCallback().progress.push(0, 100) 67 pisiprogress.getCallback().verbose("SyncML: Loading") 68 if_calendar = SyncmlModule.SyncmlCalendarInterface(self._url, self._username, self._password, self._database, SYNCMLSERVER_IDENTIFIER) 69 events_raw = if_calendar.downloadItems() # load 70 if_calendar.finish() 71 pisiprogress.getCallback().progress.setProgress(20) 72 pisiprogress.getCallback().update("Loading") 73 74 i = 0 75 for x in events_raw.keys(): 76 print events_raw[x] 77 content = vobject.readOne(events_raw[x]) 78 79 if content.contents.has_key('vevent'): # maybe it's an empty file - you new know ;) 80 for y in content.contents['vevent']: 81 atts, globalId, updated = vobjecttools.extractICSEntry(y) 82 if not globalId or globalId == "": 83 globalId = events.assembleID() 84 tmpEvent = events.Event( globalId, updated, atts) 85 tmpEvent.attributes['globalid'] = globalId 86 self.replaceEvent(globalId, tmpEvent) 87 else: 88 tmpEvent = events.Event(globalId, updated, atts) 89 tmpEvent.attributes['globalid'] = globalId 90 91 self._allEvents[globalId] = tmpEvent 92 self._mapping[globalId] = x 93 94 i += 1 95 pisiprogress.getCallback().progress.setProgress(20 + ((i*80) / len(events_raw))) 96 pisiprogress.getCallback().update('Loading') 97 98 pisiprogress.getCallback().progress.drop()
99
100 - def saveModifications(self):
101 """ 102 Save whatever changcalendar_syncml.pyes have come by 103 104 The history of actions for this data source is iterated. For each item in there the corresponding action is carried out on the item in question. 105 For data assembling (ICS) the tools layer in L{vobjecttools} is used. 106 """ 107 pisiprogress.getCallback().verbose("SyncML module: I apply %d changes now" %(len(self._history))) 108 if_events = SyncmlModule.SyncmlCalendarInterface(self._url, self._username, self._password, self._database, SYNCMLSERVER_IDENTIFIER) 109 110 mods = {} 111 dels = {} 112 adds = {} 113 114 i=0 115 for listItem in self._history: 116 action = listItem[0] 117 id = listItem[1] 118 if action == ACTIONID_ADD: 119 pisiprogress.getCallback().verbose( "\t\t<syncml> adding %s" %(id)) 120 c = self.getEvent(id) 121 ics = vobjecttools.createRawEventEntry(c) 122 print ics.serialize() 123 adds[str(i)] = ics.serialize() 124 elif action == ACTIONID_DELETE: 125 pisiprogress.getCallback().verbose("\t\t<syncml> deleting %s" %(id)) 126 syncml_id = self._mapping[id] 127 dels[syncml_id] = "" 128 elif action == ACTIONID_MODIFY: 129 pisiprogress.getCallback().verbose("\t\t<syncml> replacing %s" %(id)) 130 c = self.getEvent(id) 131 syncml_id = self._mapping[id] 132 ics = vobjecttools.createRawEventEntry(c, True) 133 # mods[syncml_id] = vcard.serialize() # causing problems - no proper replacement 134 dels[syncml_id] = "" 135 adds[str(i)] = ics.serialize() 136 i+=1 137 pisiprogress.getCallback().progress.setProgress(i * 90 / len(self._history)) 138 pisiprogress.getCallback().update('Storing') 139 140 if_events.applyChanges(mods = mods, dels = dels, adds = adds) 141 if_events.finish() 142 pisiprogress.getCallback().progress.setProgress(100) 143 pisiprogress.getCallback().update('Storing')
144