1.1 --- a/tools/make_freebusy.py Sat Jul 25 18:19:33 2015 +0200
1.2 +++ b/tools/make_freebusy.py Sat Jul 25 19:13:32 2015 +0200
1.3 @@ -1,5 +1,11 @@
1.4 #!/usr/bin/env python
1.5
1.6 +"""
1.7 +Construct free/busy records for a user, either recording that user's own
1.8 +availability schedule or the schedule of another user (using details provided
1.9 +when scheduling events with that user).
1.10 +"""
1.11 +
1.12 from imiptools.data import get_window_end, Object
1.13 from imiptools.dates import format_datetime, get_default_timezone, to_recurrence_start
1.14 from imiptools.period import FreeBusyPeriod, is_replaced
1.15 @@ -9,7 +15,10 @@
1.16
1.17 def get_periods(fb, obj, tzid, window_end, only_organiser, recurrenceids):
1.18
1.19 - # Update free/busy details with the actual periods associated with the event.
1.20 + """
1.21 + Update free/busy details 'fb' with the actual periods associated with the
1.22 + event 'obj'.
1.23 + """
1.24
1.25 recurrenceid = obj.get_recurrenceid()
1.26 recurrenceids = [to_recurrence_start(r) for r in recurrenceids]
1.27 @@ -29,99 +38,103 @@
1.28
1.29 # Main program.
1.30
1.31 -try:
1.32 - user = sys.argv[1]
1.33 - args = sys.argv[2:]
1.34 - participant = args and args[0] not in ("-n", "-s", "-v") and args[0] or user
1.35 - store_and_publish = "-s" in args
1.36 - include_needs_action = "-n" in args
1.37 - verbose = "-v" in args
1.38 -except IndexError:
1.39 - print >>sys.stderr, """\
1.40 -Need a user and an optional participant (if different from the user),
1.41 -along with the -s option if updating the store and the published details.
1.42 -"""
1.43 - sys.exit(1)
1.44 +if __name__ == "__main__":
1.45 +
1.46 + # Interpret the command line arguments.
1.47
1.48 -preferences = Preferences(user)
1.49 -tzid = preferences.get("TZID") or get_default_timezone()
1.50 + try:
1.51 + user = sys.argv[1]
1.52 + args = sys.argv[2:]
1.53 + participant = args and args[0] not in ("-n", "-s", "-v") and args[0] or user
1.54 + store_and_publish = "-s" in args
1.55 + include_needs_action = "-n" in args
1.56 + verbose = "-v" in args
1.57 + except IndexError:
1.58 + print >>sys.stderr, """\
1.59 + Need a user and an optional participant (if different from the user),
1.60 + along with the -s option if updating the store and the published details.
1.61 + """
1.62 + sys.exit(1)
1.63
1.64 -# Get the size of the free/busy window.
1.65 + preferences = Preferences(user)
1.66 + tzid = preferences.get("TZID") or get_default_timezone()
1.67 +
1.68 + # Get the size of the free/busy window.
1.69
1.70 -try:
1.71 - window_size = int(preferences.get("window_size"))
1.72 -except (TypeError, ValueError):
1.73 - window_size = 100
1.74 -window_end = get_window_end(tzid, window_size)
1.75 + try:
1.76 + window_size = int(preferences.get("window_size"))
1.77 + except (TypeError, ValueError):
1.78 + window_size = 100
1.79 + window_end = get_window_end(tzid, window_size)
1.80
1.81 -store = FileStore()
1.82 -publisher = FilePublisher()
1.83 + store = FileStore()
1.84 + publisher = FilePublisher()
1.85
1.86 -# Get all identifiers for events.
1.87 + # Get all identifiers for events.
1.88
1.89 -uids = store.get_events(user)
1.90 + uids = store.get_events(user)
1.91
1.92 -all_events = set()
1.93 -for uid in uids:
1.94 - all_events.add((uid, None))
1.95 - all_events.update([(uid, recurrenceid) for recurrenceid in store.get_recurrences(user, uid)])
1.96 + all_events = set()
1.97 + for uid in uids:
1.98 + all_events.add((uid, None))
1.99 + all_events.update([(uid, recurrenceid) for recurrenceid in store.get_recurrences(user, uid)])
1.100
1.101 -# Filter out cancelled events.
1.102 + # Filter out cancelled events.
1.103
1.104 -cancelled = store.get_cancellations(user) or []
1.105 -all_events.difference_update(cancelled)
1.106 + cancelled = store.get_cancellations(user) or []
1.107 + all_events.difference_update(cancelled)
1.108
1.109 -# Obtain event objects.
1.110 + # Obtain event objects.
1.111
1.112 -objs = []
1.113 -for uid, recurrenceid in all_events:
1.114 - if verbose:
1.115 - print >>sys.stderr, uid, recurrenceid
1.116 - event = store.get_event(user, uid, recurrenceid)
1.117 - if event:
1.118 - objs.append(Object(event))
1.119 + objs = []
1.120 + for uid, recurrenceid in all_events:
1.121 + if verbose:
1.122 + print >>sys.stderr, uid, recurrenceid
1.123 + event = store.get_event(user, uid, recurrenceid)
1.124 + if event:
1.125 + objs.append(Object(event))
1.126
1.127 -# Build a free/busy collection for the given user.
1.128 + # Build a free/busy collection for the given user.
1.129
1.130 -fb = []
1.131 -for obj in objs:
1.132 - attendees = obj.get_value_map("ATTENDEE")
1.133 - organiser = obj.get_value("ORGANIZER")
1.134 - recurrenceids = store.get_recurrences(user, obj.get_value("UID"))
1.135 + fb = []
1.136 + for obj in objs:
1.137 + attendees = obj.get_value_map("ATTENDEE")
1.138 + organiser = obj.get_value("ORGANIZER")
1.139 + recurrenceids = store.get_recurrences(user, obj.get_value("UID"))
1.140
1.141 - for attendee, attendee_attr in attendees.items():
1.142 + for attendee, attendee_attr in attendees.items():
1.143
1.144 - # Only consider events where the stated participant actually attends.
1.145 + # Only consider events where the stated participant actually attends.
1.146
1.147 - if attendee == participant:
1.148 - partstat = attendee_attr.get("PARTSTAT", "NEEDS-ACTION")
1.149 + if attendee == participant:
1.150 + partstat = attendee_attr.get("PARTSTAT", "NEEDS-ACTION")
1.151
1.152 - if partstat not in ("DECLINED", "DELEGATED", "NEEDS-ACTION") or \
1.153 - include_needs_action and partstat == "NEEDS-ACTION":
1.154 + if partstat not in ("DECLINED", "DELEGATED", "NEEDS-ACTION") or \
1.155 + include_needs_action and partstat == "NEEDS-ACTION":
1.156
1.157 - get_periods(fb, obj, tzid, window_end, False, recurrenceids)
1.158 + get_periods(fb, obj, tzid, window_end, False, recurrenceids)
1.159
1.160 - break
1.161 + break
1.162
1.163 - # Where not attending, retain the affected periods and mark them as
1.164 - # organising periods.
1.165 + # Where not attending, retain the affected periods and mark them as
1.166 + # organising periods.
1.167
1.168 - else:
1.169 - if organiser == participant:
1.170 - get_periods(fb, obj, tzid, window_end, True, recurrenceids)
1.171 + else:
1.172 + if organiser == participant:
1.173 + get_periods(fb, obj, tzid, window_end, True, recurrenceids)
1.174
1.175 -fb.sort()
1.176 + fb.sort()
1.177
1.178 -# Store and publish the free/busy collection.
1.179 + # Store and publish the free/busy collection.
1.180
1.181 -if store_and_publish:
1.182 - if user == participant:
1.183 - store.set_freebusy(user, fb)
1.184 - publisher.set_freebusy(user, fb)
1.185 + if store_and_publish:
1.186 + if user == participant:
1.187 + store.set_freebusy(user, fb)
1.188 + publisher.set_freebusy(user, fb)
1.189 + else:
1.190 + store.set_freebusy_for_other(user, fb, participant)
1.191 else:
1.192 - store.set_freebusy_for_other(user, fb, participant)
1.193 -else:
1.194 - for item in fb:
1.195 - print "\t".join(item.as_tuple(strings_only=True))
1.196 + for item in fb:
1.197 + print "\t".join(item.as_tuple(strings_only=True))
1.198
1.199 # vim: tabstop=4 expandtab shiftwidth=4