1.1 --- a/imip_store.py Sun Aug 09 23:24:29 2015 +0200
1.2 +++ b/imip_store.py Tue Aug 11 23:53:54 2015 +0200
1.3 @@ -22,7 +22,7 @@
1.4 from datetime import datetime
1.5 from imiptools.config import STORE_DIR, PUBLISH_DIR
1.6 from imiptools.data import make_calendar, parse_object, to_stream
1.7 -from imiptools.dates import format_datetime
1.8 +from imiptools.dates import format_datetime, get_datetime
1.9 from imiptools.filesys import fix_permissions, FileBase
1.10 from imiptools.period import FreeBusyPeriod
1.11 from os.path import exists, isfile, join
1.12 @@ -70,7 +70,7 @@
1.13 try:
1.14 l = []
1.15 for line in f.readlines():
1.16 - t = line.strip().split("\t")
1.17 + t = line.strip(" \r\n").split("\t")
1.18 if empty_defaults:
1.19 t = self._set_defaults(t, empty_defaults)
1.20 l.append(tuple(t))
1.21 @@ -341,6 +341,40 @@
1.22
1.23 return True
1.24
1.25 + # Free/busy period providers, upon extension of the free/busy records.
1.26 +
1.27 + def get_freebusy_providers(self, user, dt=None):
1.28 +
1.29 + """
1.30 + Return a set of uncancelled events of the form (uid, recurrenceid)
1.31 + providing free/busy details beyond the given datetime 'dt'.
1.32 + """
1.33 +
1.34 + filename = self.get_object_in_store(user, "freebusy-providers")
1.35 + if not filename or not exists(filename):
1.36 + return None
1.37 + else:
1.38 + # Attempt to read providers, with a declaration of the datetime
1.39 + # from which such providers are considered as still being active.
1.40 +
1.41 + t = self._get_table(user, filename, [(1, None)])
1.42 + try:
1.43 + dt_string = t[0][0]
1.44 + except IndexError:
1.45 + return None
1.46 +
1.47 + # If the requested datetime is earlier than the stated datetime, the
1.48 + # providers will need to be recomputed.
1.49 +
1.50 + if dt:
1.51 + providers_dt = get_datetime(dt_string)
1.52 + if not providers_dt or providers_dt > dt:
1.53 + return None
1.54 +
1.55 + # Otherwise, return the providers.
1.56 +
1.57 + return t[1:]
1.58 +
1.59 # Free/busy period access.
1.60
1.61 def get_freebusy(self, user):
2.1 --- a/tools/make_freebusy.py Sun Aug 09 23:24:29 2015 +0200
2.2 +++ b/tools/make_freebusy.py Tue Aug 11 23:53:54 2015 +0200
2.3 @@ -21,6 +21,7 @@
2.4 this program. If not, see <http://www.gnu.org/licenses/>.
2.5 """
2.6
2.7 +from bisect import bisect_left
2.8 from codecs import getwriter
2.9 from imiptools.data import get_window_end, Object
2.10 from imiptools.dates import get_default_timezone
2.11 @@ -62,9 +63,23 @@
2.12 store = FileStore()
2.13 publisher = FilePublisher()
2.14
2.15 - # Get identifiers for uncancelled events.
2.16 + # Get identifiers for uncancelled events either from a list of events
2.17 + # providing free/busy periods at the end of the given time window, or from
2.18 + # a list of all events.
2.19 +
2.20 + all_events = store.get_freebusy_providers(user, window_end)
2.21
2.22 - all_events = store.get_active_events(user)
2.23 + if not all_events:
2.24 + all_events = store.get_active_events(user)
2.25 + fb = []
2.26 +
2.27 + # With providers of additional periods, append to the existing collection.
2.28 +
2.29 + else:
2.30 + if user == participant:
2.31 + fb = store.get_freebusy(user)
2.32 + else:
2.33 + fb = store.get_freebusy_for_other(user, participant)
2.34
2.35 # Obtain event objects.
2.36
2.37 @@ -78,16 +93,18 @@
2.38
2.39 # Build a free/busy collection for the given user.
2.40
2.41 - fb = []
2.42 for obj in objs:
2.43 partstat = obj.get_participation_status(participant)
2.44 recurrenceids = not obj.get_recurrenceid() and store.get_recurrences(user, obj.get_uid())
2.45
2.46 if obj.get_participation(partstat, include_needs_action):
2.47 for p in obj.get_active_periods(recurrenceids, tzid, window_end):
2.48 - fb.append(obj.get_freebusy_period(p, partstat == "ORG"))
2.49 -
2.50 - fb.sort()
2.51 + fbp = obj.get_freebusy_period(p, partstat == "ORG")
2.52 + i = bisect_left(fb, fbp)
2.53 + if i == len(fb):
2.54 + fb.append(fbp)
2.55 + elif fb[i] != fbp:
2.56 + fb.insert(i, fbp)
2.57
2.58 # Store and publish the free/busy collection.
2.59