iis: comparsion of two lists
Matej Cepl
cepl.m at neu.edu
Fri Apr 26 18:49:24 EDT 2002
Hi,
I am newbie in Python world and non-programmer (and totally
enjoying power of Python). I have begun to write a small script
for synchronization of two IMAP folders (it seems, there is
nothing like that all over the Net) and everything goes well (if
anybody wants to comments, he is very welcomed; unfinished draft
is attached), but for one operation. I would like to compare two
list of messages (in the local and remote folders) and create
list of messages, to be deleted/downloaded. In plain Python, the
part of deletion would go like this:
erase = ()
for msg in proc_old:
if not(msg in loc_old):
erase.append(msg)
Of course, it is crucial part of the script, so I would like to
optimize it by using map() function. Could I do something like
this?:
map(lambda m: if not(msg in loc_old): erase.append(msg), proc_old)
Thanks for any comments
Matej Cepl
--
Matej Cepl, cepl.m at neu.edu
138 Highland Ave. #10, Somerville, Ma 02143, (617) 623-1488
Opinions founded on prejudice are always sustained with the
greatest violence.
-- Hebrew Proverb
-------------- next part --------------
#!/usr/bin/env python
# $Id: iis.py,v 0.6 2002/04/26 22:42:01 matej Exp $
"""
IMAP-IMAP Synchronization - iis
(always use lower case to avoid terrible misunderstanding :-)
Copyright (c) 2002 Matej Cepl <matej at ceplovi.cz>
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
"""
import ConfigParser
import imaplib
from sys import stderr, exit
from string import split, join
from os.path import expanduser
# constants
# return errorlevels
DOWNERR = 1
UPERR = 2
SELECTERR = 3
LISTERR = 4
LOGINERR = 5
CONFIGERR = 10
# other constants
IMAPPORT = "143"
def chatch_error(errmsg,stat_num):
stderr.write("IMAP Error: %s !\n" % errmsg)
exit(stat_num)
class Conifg(ConfigParser.ConfigParser):
"""
Object containing configuration.
It reads configuration file (in WIN .ini syntax) like this
[localuser1]
local = password
server1.com = username,password,last_sync (in IMAP shape)
[localuser2]
local = password
server2.com = username,password,last_sync (in IMAP shape)
"""
def __init__(self,fname=".iisrc"):
ConfigParser.ConfigParser.__ini__(self)
self.filename = expanduser("~/"+fname)
try:
self.read(self.filename)
except ParsingError,e:
chatch_error(e,CONFIGERR)
## read configuration file and fill appropriate data
## structures
def self.close()
## write changed values to configuration file
def comp_lists(processed,local):
"""
Compare two lists of messages and select for download/delete.
INPUT: two objects Server -- one to be processed and other
OUTPUT: erase, download -- list of messages to delete from
the processed server, and list of messages to be
downloaded on other server
What is newer than self.last and it isn't in other, should be
downloaded from processed, and what is older and isn't on
other, should be deleted. The same other way around.
"""
proc_old = processed.old_msg.keys()
proc_new = processed.new_msg.keys()
loc_old = local.old_msg.keys()
loc_new = local.new_msg.keys()
erase = ()
download = ()
map(lambda m: if not(msg in loc_old): erase.append(msg), proc_old)
map(lambda m: if not(msg in loc_new): download.append(msg), proc_new)
return erase,download
def sync(loc,rem):
"""
Synchronize two folders on servers.
## INPUT:
## OUTPUT:
## description
"""
# delete old on the remote and download new messages
delete,down = comp_lists(rem,loc)
try:
ok, answer = rem.store(join(delete), 'FLAGS', '(\Deleted)')
except Exception,e:
stderr.write("Remote messages were not deleted!\n")
# rather let it be -- it is better not to have
# something deleted, than to have deleted more than
# we want
for msg in down:
try:
stuff = rem.fetch(msg,'(RFC822)')
# tohle musim nejak dodelat
# loc.append(mailbox,flags,date,message)
except Exception,e:
catch_error(e,DOWNERR)
# delete old on local and upload new ones
delete,up = comp_lists(loc,rem)
try:
ok, answer = loc.store(join(delete), 'FLAGS', '(\Deleted)')
except Exception,e:
stderr.write("Local messages were not deleted!\n")
for msg in up:
try:
stuff = loc.fetch(msg,'(RFC822)')
# I have to add something here ... :-)
# rem.append(mailbox,flags,date,message)
# date - expected tuple according to library time
except Exception,e:
catch_error(e,UPERR)
class Server(imaplib.IMAP4):
"""
Main class for managing IMAP servers and folders.
## some description
"""
def __init__(self,server,port=IMAPPORT,user,password,last_sync):
"""
Connect to the server and login.
"""
self.host=server
self.port=port
self.user=user
self.passwd=password
self.last=last_sync
self.new_msg={}
self.old_msg={}
try:
imaplib.IMAP4.__init__(self,self.host,self.port)
self.login(self.user,self.passwd)
except Exception,e:
catch_error(e,UPERR)
def message_lists(self,folder="")
"""
Fetch list of messages, that are older than self.last and
newer than that.
INPUT: correctly opened IMAP server, name of the folder,
correctly set self.last (in IMAP representation).
OUTPUT: sets self.new_msg and self.old_msg.
"""
if folder=="":
folder="INBOX"
try:
self.select(folder)
except Exception,e:
catch_error(e,SELECTERR)
try:
ok, stuff = self.search(None,'( UNDELETED SINCE ' + self.last + ' )')
if ok == 'OK':
for msg in split(stuff):
ok, header = self.fetch(msg,'(UID)')
if ok == 'OK':
uid = split(header[0])[2][:-1]
ok, header = self.fetch(msg,'(INTERNALDATE)')
if ok == 'OK':
temptup = split(header[0])[2:]
tstr = temptup[0][1:] + temptup[1] + temptup[2][:-2]
date = imaplib.Internaldate2tuple(tstr)
self.new_msg[msg]=uid,date
ok, stuff = self.search(None,'( UNDELETED BEFORE ' + self.last + ' )')
if ok == 'OK':
for msg in split(stuff):
ok, header = self.fetch(msg,'(UID)')
if ok == 'OK':
uid = split(header[0])[2][:-1]
ok, header = self.fetch(msg,'(INTERNALDATE)')
if ok == 'OK':
temptup = split(header[0])[2:]
tstr = temptup[0][1:] + temptup[1] + temptup[2][:-2]
date = imaplib.Internaldate2tuple(tstr)
self.old_msg[msg]=uid,date
except Exception,e:
catch_error(e,LISTERR)
self.close()
def complete(self):
"""
leave server
"""
self.logout()
if __name__ == '__main__':
## General outline
conf = Config()
## for users:
## local = Server(...)
## local.message_lists()
## for servers:
## remote = Server(...)
## remote.message_lists()
## sync(local,remote)
conf.close()
# vim: set ts=3:
More information about the Python-list
mailing list