1.1 --- a/imiptools/client.py Mon Oct 16 22:10:22 2017 +0200
1.2 +++ b/imiptools/client.py Mon Oct 16 23:37:59 2017 +0200
1.3 @@ -22,11 +22,13 @@
1.4 from collections import OrderedDict
1.5 from datetime import datetime, timedelta
1.6 from imiptools.config import settings
1.7 -from imiptools.data import check_delegation, get_address, get_uri, \
1.8 +from imiptools.data import check_delegation, get_address, \
1.9 get_recurrence_periods, \
1.10 + get_sender_identities, get_uri, \
1.11 get_window_end, is_new_object, make_freebusy, \
1.12 - make_uid, new_object, to_part, uri_dict, uri_item, \
1.13 - uri_items, uri_parts, uri_values
1.14 + make_uid, new_object, to_part, \
1.15 + update_attendees_with_delegates, \
1.16 + uri_dict, uri_item, uri_items, uri_parts, uri_values
1.17 from imiptools.dates import check_permitted_values, format_datetime, \
1.18 get_datetime, get_default_timezone, \
1.19 get_duration, get_time, get_timestamp, \
1.20 @@ -585,12 +587,21 @@
1.21
1.22 # Search for the sender of the message or the calendar system address.
1.23
1.24 - senders = self.senders or self.messenger and [self.messenger.sender] or []
1.25 + senders = set(uri_values(self.senders or self.messenger and [self.messenger.sender] or []))
1.26 +
1.27 + if senders:
1.28 +
1.29 + # Obtain a mapping from sender URI to attendee URI, where the sender
1.30 + # is taken from the SENT-BY attribute if present, or from the
1.31 + # attendee value otherwise.
1.32
1.33 - for attendee, attendee_attr in uri_items(self.obj.get_items("ATTENDEE") or []):
1.34 - if get_address(attendee) in senders or \
1.35 - get_address(attendee_attr.get("SENT-BY")) in senders:
1.36 - return get_uri(attendee)
1.37 + sent_by = get_sender_identities(uri_dict(self.obj.get_value_map("ATTENDEE")))
1.38 +
1.39 + # Obtain the attendee for the first sender matching the SENT-BY or
1.40 + # attendee value.
1.41 +
1.42 + for sender in senders.intersection(sent_by.keys()):
1.43 + return sent_by[sender][0]
1.44
1.45 return None
1.46
1.47 @@ -634,32 +645,21 @@
1.48
1.49 # Get attendee details in a usable form.
1.50
1.51 - attendee_map = uri_dict(obj.get_value_map("ATTENDEE"))
1.52 + stored_attendees = uri_dict(obj.get_value_map("ATTENDEE"))
1.53
1.54 for attendee, attendee_attr in attendees.items():
1.55
1.56 # Update attendance in the loaded object for any recognised
1.57 # attendees.
1.58
1.59 - if attendee_map.has_key(attendee):
1.60 - attendee_map[attendee] = attendee_attr
1.61 -
1.62 - # Check for delegated attendees.
1.63 -
1.64 - for attendee, attendee_attr in attendees.items():
1.65 + if stored_attendees.has_key(attendee):
1.66 + stored_attendees[attendee] = attendee_attr
1.67
1.68 - # Identify delegates and check the delegation using the updated
1.69 - # attendee information.
1.70 -
1.71 - if not attendee_map.has_key(attendee) and \
1.72 - attendee_attr.has_key("DELEGATED-FROM") and \
1.73 - check_delegation(attendee_map, attendee, attendee_attr):
1.74 -
1.75 - attendee_map[attendee] = attendee_attr
1.76 + update_attendees_with_delegates(stored_attendees, attendees)
1.77
1.78 # Set the new details and store the object.
1.79
1.80 - obj["ATTENDEE"] = attendee_map.items()
1.81 + obj["ATTENDEE"] = stored_attendees.items()
1.82
1.83 # Set a specific recurrence or the complete event if not an additional
1.84 # occurrence.
2.1 --- a/imiptools/data.py Mon Oct 16 22:10:22 2017 +0200
2.2 +++ b/imiptools/data.py Mon Oct 16 23:37:59 2017 +0200
2.3 @@ -1319,7 +1319,8 @@
2.4 """
2.5 Return a mapping from actual senders to the identities for which they
2.6 have provided data, extracting this information from the given
2.7 - 'mapping'.
2.8 + 'mapping'. The SENT-BY attribute provides sender information in preference
2.9 + to the property values given as the mapping keys.
2.10 """
2.11
2.12 senders = {}
2.13 @@ -1348,4 +1349,24 @@
2.14
2.15 return to_timezone(start or datetime.now(), tzid) + timedelta(days)
2.16
2.17 +def update_attendees_with_delegates(stored_attendees, attendees):
2.18 +
2.19 + """
2.20 + Update the 'stored_attendees' mapping with delegate information from the
2.21 + given 'attendees' mapping.
2.22 + """
2.23 +
2.24 + # Check for delegated attendees.
2.25 +
2.26 + for attendee, attendee_attr in attendees.items():
2.27 +
2.28 + # Identify delegates and check the delegation using the updated
2.29 + # attendee information.
2.30 +
2.31 + if not stored_attendees.has_key(attendee) and \
2.32 + attendee_attr.has_key("DELEGATED-FROM") and \
2.33 + check_delegation(stored_attendees, attendee, attendee_attr):
2.34 +
2.35 + stored_attendees[attendee] = attendee_attr
2.36 +
2.37 # vim: tabstop=4 expandtab shiftwidth=4
3.1 --- a/imiptools/handlers/__init__.py Mon Oct 16 22:10:22 2017 +0200
3.2 +++ b/imiptools/handlers/__init__.py Mon Oct 16 23:37:59 2017 +0200
3.3 @@ -145,7 +145,13 @@
3.4
3.5 # Return the true identities.
3.6
3.7 - return reduce(lambda a, b: a + b, [identities[get_uri(address)] for address in valid], [])
3.8 + attendees = []
3.9 + for address in valid:
3.10 + attendees += identities[get_uri(address)]
3.11 + return attendees
3.12 +
3.13 + # Rely on the mapping keys being accessible as a sequence.
3.14 +
3.15 else:
3.16 return mapping
3.17
3.18 @@ -159,6 +165,9 @@
3.19 if self.recipient:
3.20 addresses = set(map(get_address, mapping))
3.21 return map(get_uri, addresses.intersection([self.recipient]))
3.22 +
3.23 + # Rely on the mapping keys being accessible as a sequence.
3.24 +
3.25 else:
3.26 return mapping
3.27