split ics files in-script, get rid of ext modules
This commit is contained in:
parent
f385ff4f1a
commit
cd74699694
@ -2670,10 +2670,7 @@ while query.next >= 0 and query.next < nres:
|
|||||||
url="http://www.jedrea.com/chmlib/">chmlib</ulink>).</para>
|
url="http://www.jedrea.com/chmlib/">chmlib</ulink>).</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
|
|
||||||
<listitem><para>ics: iCalendar files need Python and the
|
<listitem><para>ics: iCalendar files need Python.</para></listitem>
|
||||||
<ulink url=" http://codespeak.net/icalendar/">icalendar</ulink>
|
|
||||||
module.</para>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem><para>zip: Zip archives need Python (and the standard
|
<listitem><para>zip: Zip archives need Python (and the standard
|
||||||
zipfile module).</para>
|
zipfile module).</para>
|
||||||
|
|||||||
@ -1,25 +1,48 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
# Read an ICS file, break it into "documents" which are events, todos,
|
||||||
|
# or journal entries, and interface with recoll execm
|
||||||
|
#
|
||||||
|
# For historical reasons, this can use either the icalendar or the
|
||||||
|
# vobject Python modules, or an internal splitter. The default is now
|
||||||
|
# to use the internal splitter, the other modules are more trouble
|
||||||
|
# than they're worth (to us and until we will want to get into date
|
||||||
|
# computations etc.)
|
||||||
|
|
||||||
import rclexecm
|
import rclexecm
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
try:
|
# Decide how we'll process the file.
|
||||||
from icalendar import Calendar, Event
|
modules = ('internal', 'icalendar', 'vobject')
|
||||||
except:
|
usemodule = 'internal'
|
||||||
print "RECFILTERROR HELPERNOTFOUND python:icalendar"
|
forcevobject = 0
|
||||||
sys.exit(1);
|
if usemodule != 'internal':
|
||||||
|
try:
|
||||||
|
if forcevobject:
|
||||||
|
raise Exception
|
||||||
|
from icalendar import Calendar, Event
|
||||||
|
usemodule = 'icalendar'
|
||||||
|
except:
|
||||||
|
try:
|
||||||
|
import vobject
|
||||||
|
usemodule = 'vobject'
|
||||||
|
except:
|
||||||
|
print "RECFILTERROR HELPERNOTFOUND python:icalendar"
|
||||||
|
print "RECFILTERROR HELPERNOTFOUND python:vobject"
|
||||||
|
sys.exit(1);
|
||||||
|
|
||||||
|
|
||||||
class IcalExtractor:
|
class IcalExtractor:
|
||||||
def __init__(self, em):
|
def __init__(self, em):
|
||||||
self.file = ""
|
self.file = ""
|
||||||
self.contents = []
|
self.contents = []
|
||||||
self.em = em
|
self.em = em
|
||||||
em.setmimetype("text/plain")
|
self.em.setmimetype("text/plain")
|
||||||
|
|
||||||
def extractone(self, index):
|
def extractone(self, index):
|
||||||
if index >= len(self.contents):
|
if index >= len(self.contents):
|
||||||
return(False, "", "", True)
|
return(False, "", "", True)
|
||||||
docdata = self.contents[index].as_string()
|
docdata = self.contents[index]
|
||||||
#self.em.rclog(docdata)
|
#self.em.rclog(docdata)
|
||||||
|
|
||||||
iseof = rclexecm.RclExecM.noteof
|
iseof = rclexecm.RclExecM.noteof
|
||||||
@ -30,13 +53,39 @@ class IcalExtractor:
|
|||||||
###### File type handler api, used by rclexecm ---------->
|
###### File type handler api, used by rclexecm ---------->
|
||||||
def openfile(self, params):
|
def openfile(self, params):
|
||||||
self.file = params["filename:"]
|
self.file = params["filename:"]
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.cal = Calendar.from_string(open(self.file,'rb').read())
|
calstr = open(self.file, 'rb')
|
||||||
except:
|
except Exception, e:
|
||||||
|
self.em.rclog("Openfile: open: %s" % str(e))
|
||||||
return False
|
return False
|
||||||
# Skip the top level object
|
|
||||||
self.currentindex = 1
|
self.currentindex = 0
|
||||||
self.contents = self.cal.walk()
|
|
||||||
|
if usemodule == 'internal':
|
||||||
|
self.contents = ICalSimpleSplitter().splitcalendar(calstr)
|
||||||
|
elif usemodule == 'icalendar':
|
||||||
|
try:
|
||||||
|
cal = Calendar.from_string(calstr.read())
|
||||||
|
except Exception, e:
|
||||||
|
self.em.rclog("Openfile: read or parse error: %s" % str(e))
|
||||||
|
return False
|
||||||
|
self.contents = cal.walk()
|
||||||
|
self.contents = [item.as_string() for item in self.contents
|
||||||
|
if (item.name == 'VEVENT' or item.name == 'VTODO'
|
||||||
|
or item.name == 'VJOURNAL')]
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
cal = vobject.readOne(calstr)
|
||||||
|
except Exception, e:
|
||||||
|
self.em.rclog("Openfile: cant parse object: %s" % str(e))
|
||||||
|
return False
|
||||||
|
for lstnm in ('vevent_list', 'vtodo_list', 'vjournal_list'):
|
||||||
|
lst = getattr(cal, lstnm, [])
|
||||||
|
for ev in lst:
|
||||||
|
self.contents.append(ev.serialize())
|
||||||
|
|
||||||
|
#self.em.rclog("openfile: Entry count: %d"%(len(self.contents)))
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def getipath(self, params):
|
def getipath(self, params):
|
||||||
@ -48,12 +97,84 @@ class IcalExtractor:
|
|||||||
|
|
||||||
def getnext(self, params):
|
def getnext(self, params):
|
||||||
if self.currentindex >= len(self.contents):
|
if self.currentindex >= len(self.contents):
|
||||||
#em.rclog("getnext: EOF hit")
|
self.em.rclog("getnext: EOF hit")
|
||||||
return (False, "", "", rclexecm.RclExecM.eofnow)
|
return (False, "", "", rclexecm.RclExecM.eofnow)
|
||||||
else:
|
else:
|
||||||
ret= self.extractone(self.currentindex)
|
ret= self.extractone(self.currentindex)
|
||||||
self.currentindex += 1
|
self.currentindex += 1
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
# Trivial splitter: cut objects on BEGIN/END (only for 'interesting' objects)
|
||||||
|
# ignore all other syntax
|
||||||
|
class ICalSimpleSplitter:
|
||||||
|
# Note that if an 'interesting' element is nested inside another one,
|
||||||
|
# it will not be extracted (stay as text in external event). This is
|
||||||
|
# not an issue and I don't think it can happen with the current list
|
||||||
|
interesting = ('VTODO', 'VEVENT', 'VJOURNAL')
|
||||||
|
|
||||||
|
def splitcalendar(self, fin):
|
||||||
|
curblkname = ''
|
||||||
|
curblk = ''
|
||||||
|
|
||||||
|
lo = []
|
||||||
|
for line in fin:
|
||||||
|
line = line.rstrip()
|
||||||
|
if line == '':
|
||||||
|
continue
|
||||||
|
|
||||||
|
if curblkname:
|
||||||
|
curblk = curblk + line + "\n"
|
||||||
|
|
||||||
|
l = line.split(":")
|
||||||
|
if len(l) < 2:
|
||||||
|
continue
|
||||||
|
|
||||||
|
# If not currently inside a block and we see an
|
||||||
|
# 'interesting' BEGIN, start block
|
||||||
|
if curblkname == '' and l[0].upper() == "BEGIN" :
|
||||||
|
name = l[1].upper()
|
||||||
|
if name in ICalSimpleSplitter.interesting:
|
||||||
|
curblkname = name
|
||||||
|
curblk = curblk + line + "\n"
|
||||||
|
|
||||||
|
# If currently accumulating block lines, check for end
|
||||||
|
if curblkname and l[0].upper() == "END" and \
|
||||||
|
l[1].upper() == curblkname:
|
||||||
|
lo.append(curblk)
|
||||||
|
curblkname = ''
|
||||||
|
curblk = ''
|
||||||
|
|
||||||
|
if curblk:
|
||||||
|
lo.append(curblk)
|
||||||
|
curblkname = ''
|
||||||
|
curblk = ''
|
||||||
|
|
||||||
|
return lo
|
||||||
|
|
||||||
|
|
||||||
|
##### Main program: either talk to the parent or execute test loop
|
||||||
|
|
||||||
e = rclexecm.RclExecM()
|
e = rclexecm.RclExecM()
|
||||||
e.mainloop(IcalExtractor(e))
|
ical = IcalExtractor(e)
|
||||||
|
|
||||||
|
if len(sys.argv) == 1:
|
||||||
|
e.mainloop(ical)
|
||||||
|
else:
|
||||||
|
# Got a file name parameter: testing without an execm parent
|
||||||
|
# Loop on all entries
|
||||||
|
if not ical.openfile({'filename:':sys.argv[1]}):
|
||||||
|
print "Open error"
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
ecnt = 0
|
||||||
|
while 1:
|
||||||
|
ok, data, ipath, eof = ical.getnext("")
|
||||||
|
if ok:
|
||||||
|
ecnt = ecnt + 1
|
||||||
|
print "=========== ENTRY %d =================" % ecnt
|
||||||
|
print data
|
||||||
|
print
|
||||||
|
else:
|
||||||
|
print "Got error, eof %d"%eof
|
||||||
|
break
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user