imip-agent

Change of imiptools/client.py

1039:a12150034cbd
imiptools/client.py
     1.1 --- a/imiptools/client.py	Sun Feb 07 23:35:20 2016 +0100
     1.2 +++ b/imiptools/client.py	Mon Feb 08 00:14:53 2016 +0100
     1.3 @@ -3,7 +3,7 @@
     1.4  """
     1.5  Common calendar client utilities.
     1.6  
     1.7 -Copyright (C) 2014, 2015 Paul Boddie <paul@boddie.org.uk>
     1.8 +Copyright (C) 2014, 2015, 2016 Paul Boddie <paul@boddie.org.uk>
     1.9  
    1.10  This program is free software; you can redistribute it and/or modify it under
    1.11  the terms of the GNU General Public License as published by the Free Software
    1.12 @@ -40,17 +40,19 @@
    1.13      default_window_size = 100
    1.14      organiser_methods = "ADD", "CANCEL", "DECLINECOUNTER", "PUBLISH", "REQUEST"
    1.15  
    1.16 -    def __init__(self, user, messenger=None, store=None, publisher=None, preferences_dir=None):
    1.17 +    def __init__(self, user, messenger=None, store=None, publisher=None, journal=None,
    1.18 +                 preferences_dir=None):
    1.19  
    1.20          """
    1.21          Initialise a calendar client with the current 'user', plus any
    1.22 -        'messenger', 'store' and 'publisher' objects, indicating any specific
    1.23 -        'preferences_dir'.
    1.24 +        'messenger', 'store', 'publisher' and 'journal' objects, indicating any
    1.25 +        specific 'preferences_dir'.
    1.26          """
    1.27  
    1.28          self.user = user
    1.29          self.messenger = messenger
    1.30          self.store = store or imip_store.FileStore()
    1.31 +        self.journal = journal or imip_store.FileJournal()
    1.32  
    1.33          try:
    1.34              self.publisher = publisher or imip_store.FilePublisher()
    1.35 @@ -71,6 +73,9 @@
    1.36      def get_publisher(self):
    1.37          return self.publisher
    1.38  
    1.39 +    def get_journal(self):
    1.40 +        return self.journal
    1.41 +
    1.42      # Store-related methods.
    1.43  
    1.44      def acquire_lock(self):
    1.45 @@ -213,23 +218,6 @@
    1.46  
    1.47      # Common operations on calendar data.
    1.48  
    1.49 -    def update_senders(self, obj=None):
    1.50 -
    1.51 -        """
    1.52 -        Update sender details in 'obj', or the current object if not indicated,
    1.53 -        removing SENT-BY attributes for attendees other than the current user if
    1.54 -        those attributes give the URI of the calendar system.
    1.55 -        """
    1.56 -
    1.57 -        obj = obj or self.obj
    1.58 -        calendar_uri = self.messenger and get_uri(self.messenger.sender)
    1.59 -        for attendee, attendee_attr in uri_items(obj.get_items("ATTENDEE")):
    1.60 -            if attendee != self.user:
    1.61 -                if attendee_attr.get("SENT-BY") == calendar_uri:
    1.62 -                    del attendee_attr["SENT-BY"]
    1.63 -            else:
    1.64 -                attendee_attr["SENT-BY"] = calendar_uri
    1.65 -
    1.66      def update_sender(self, attr):
    1.67  
    1.68          "Update the SENT-BY attribute of the 'attr' sender metadata."
    1.69 @@ -237,21 +225,6 @@
    1.70          if self.messenger and self.messenger.sender != get_address(self.user):
    1.71              attr["SENT-BY"] = get_uri(self.messenger.sender)
    1.72  
    1.73 -    def get_sending_attendee(self):
    1.74 -
    1.75 -        "Return the attendee who sent the current object."
    1.76 -
    1.77 -        # Search for the sender of the message or the calendar system address.
    1.78 -
    1.79 -        senders = self.senders or self.messenger and [self.messenger.sender] or []
    1.80 -
    1.81 -        for attendee, attendee_attr in uri_items(self.obj.get_items("ATTENDEE")):
    1.82 -            if get_address(attendee) in senders or \
    1.83 -               get_address(attendee_attr.get("SENT-BY")) in senders:
    1.84 -                return get_uri(attendee)
    1.85 -
    1.86 -        return None
    1.87 -
    1.88      def get_periods(self, obj, explicit_only=False):
    1.89  
    1.90          """
    1.91 @@ -371,31 +344,13 @@
    1.92  
    1.93          return methods, responses
    1.94  
    1.95 -    def get_unscheduled_parts(self, periods):
    1.96 -
    1.97 -        "Return message parts describing unscheduled 'periods'."
    1.98 -
    1.99 -        unscheduled_parts = []
   1.100 -
   1.101 -        if periods:
   1.102 -            obj = self.obj.copy()
   1.103 -            obj.remove_all(["RRULE", "RDATE", "DTSTART", "DTEND", "DURATION"])
   1.104 -
   1.105 -            for p in periods:
   1.106 -                if not p.origin:
   1.107 -                    continue
   1.108 -                obj["RECURRENCE-ID"] = obj["DTSTART"] = [(format_datetime(p.get_start()), p.get_start_attr())]
   1.109 -                obj["DTEND"] = [(format_datetime(p.get_end()), p.get_end_attr())]
   1.110 -                unscheduled_parts.append(obj.to_part("CANCEL"))
   1.111 -
   1.112 -        return unscheduled_parts
   1.113 -
   1.114  class ClientForObject(Client):
   1.115  
   1.116      "A client maintaining a specific object."
   1.117  
   1.118 -    def __init__(self, obj, user, messenger=None, store=None, publisher=None, preferences_dir=None):
   1.119 -        Client.__init__(self, user, messenger, store, publisher, preferences_dir)
   1.120 +    def __init__(self, obj, user, messenger=None, store=None, publisher=None,
   1.121 +                 journal=None, preferences_dir=None):
   1.122 +        Client.__init__(self, user, messenger, store, publisher, journal, preferences_dir)
   1.123          self.set_object(obj)
   1.124  
   1.125      def set_object(self, obj):
   1.126 @@ -433,6 +388,59 @@
   1.127  
   1.128          return get_uri(self.obj.get_value("ORGANIZER")) == self.user
   1.129  
   1.130 +    # Common operations on calendar data.
   1.131 +
   1.132 +    def update_senders(self, obj=None):
   1.133 +
   1.134 +        """
   1.135 +        Update sender details in 'obj', or the current object if not indicated,
   1.136 +        removing SENT-BY attributes for attendees other than the current user if
   1.137 +        those attributes give the URI of the calendar system.
   1.138 +        """
   1.139 +
   1.140 +        obj = obj or self.obj
   1.141 +        calendar_uri = self.messenger and get_uri(self.messenger.sender)
   1.142 +        for attendee, attendee_attr in uri_items(obj.get_items("ATTENDEE")):
   1.143 +            if attendee != self.user:
   1.144 +                if attendee_attr.get("SENT-BY") == calendar_uri:
   1.145 +                    del attendee_attr["SENT-BY"]
   1.146 +            else:
   1.147 +                attendee_attr["SENT-BY"] = calendar_uri
   1.148 +
   1.149 +    def get_sending_attendee(self):
   1.150 +
   1.151 +        "Return the attendee who sent the current object."
   1.152 +
   1.153 +        # Search for the sender of the message or the calendar system address.
   1.154 +
   1.155 +        senders = self.senders or self.messenger and [self.messenger.sender] or []
   1.156 +
   1.157 +        for attendee, attendee_attr in uri_items(self.obj.get_items("ATTENDEE")):
   1.158 +            if get_address(attendee) in senders or \
   1.159 +               get_address(attendee_attr.get("SENT-BY")) in senders:
   1.160 +                return get_uri(attendee)
   1.161 +
   1.162 +        return None
   1.163 +
   1.164 +    def get_unscheduled_parts(self, periods):
   1.165 +
   1.166 +        "Return message parts describing unscheduled 'periods'."
   1.167 +
   1.168 +        unscheduled_parts = []
   1.169 +
   1.170 +        if periods:
   1.171 +            obj = self.obj.copy()
   1.172 +            obj.remove_all(["RRULE", "RDATE", "DTSTART", "DTEND", "DURATION"])
   1.173 +
   1.174 +            for p in periods:
   1.175 +                if not p.origin:
   1.176 +                    continue
   1.177 +                obj["RECURRENCE-ID"] = obj["DTSTART"] = [(format_datetime(p.get_start()), p.get_start_attr())]
   1.178 +                obj["DTEND"] = [(format_datetime(p.get_end()), p.get_end_attr())]
   1.179 +                unscheduled_parts.append(obj.to_part("CANCEL"))
   1.180 +
   1.181 +        return unscheduled_parts
   1.182 +
   1.183      # Object update methods.
   1.184  
   1.185      def update_recurrenceid(self):