imip-agent

imiptools/profile.py

1050:96f9567b0a99
2016-02-08 Paul Boddie With quotas, reject indefinitely recurring events, allowing rule-based events.
     1 #!/usr/bin/env python     2      3 """     4 User profile management.     5      6 Copyright (C) 2015, 2016 Paul Boddie <paul@boddie.org.uk>     7      8 This program is free software; you can redistribute it and/or modify it under     9 the terms of the GNU General Public License as published by the Free Software    10 Foundation; either version 3 of the License, or (at your option) any later    11 version.    12     13 This program is distributed in the hope that it will be useful, but WITHOUT    14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS    15 FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more    16 details.    17     18 You should have received a copy of the GNU General Public License along with    19 this program.  If not, see <http://www.gnu.org/licenses/>.    20 """    21     22 from imiptools import config    23 from imiptools.dates import get_default_timezone    24 from imiptools.filesys import fix_permissions, FileBase    25 from os.path import exists, isdir    26 from os import listdir, makedirs    27 import codecs    28 import pytz    29     30 # Fake gettext method for strings to be translated later.    31     32 _ = lambda s: s    33     34 def identity_dict(l):    35     return dict([(i, i) for i in l])    36     37 class Preferences(FileBase):    38     39     "A simple preferences file manager."    40     41     # See: docs/wiki/Preferences    42     43     known_keys = {    44         "CN"                    : "",    45         "LANG"                  : config.LANG,    46         "TZID"                  : get_default_timezone(),    47         "add_method_response"   : config.ADD_RESPONSE_DEFAULT,    48         "event_refreshing"      : config.REFRESHING_DEFAULT,    49         "freebusy_bundling"     : config.BUNDLING_DEFAULT,    50         "freebusy_messages"     : config.NOTIFYING_DEFAULT,    51         "freebusy_offers"       : config.FREEBUSY_OFFER_DEFAULT,    52         "freebusy_publishing"   : config.PUBLISHING_DEFAULT,    53         "freebusy_sharing"      : config.SHARING_DEFAULT,    54         "incoming"              : config.INCOMING_DEFAULT,    55         "organiser_replacement" : config.ORGANISER_REPLACEMENT_DEFAULT,    56         "participating"         : config.PARTICIPATING_DEFAULT,    57         "permitted_times"       : None,    58         }    59     60     known_key_choices = {    61         "TZID"                  : identity_dict(pytz.all_timezones),    62         "add_method_response"   : {    63             "add"                   : _("Add events"),    64             "ignore"                : _("Ignore requests"),    65             "refresh"               : _("Ask for refreshed event details"),    66                                   },    67         "event_refreshing"      : {    68             "never"                 : _("Do not respond"),    69             "always"                : _("Always respond"),    70                                   },    71         "freebusy_bundling"     : {    72             "never"                 : _("Never"),    73             "always"                : _("Always"),    74                                   },    75         "freebusy_messages"     : {    76             "none"                  : _("Do not notify"),    77             "notify"                : _("Notify"),    78                                   },    79         "freebusy_publishing"   : {    80             "publish"               : _("Publish"),    81             "no"                    : _("Do not publish"),    82                                   },    83         "freebusy_sharing"      : {    84             "share"                 : _("Share"),    85             "no"                    : _("Do not share"),    86                                   },    87         "incoming"              : {    88             "message-only"          : _("Original message only"),    89             "message-then-summary"  : _("Original message followed by a separate summary message"),    90             "summary-then-message"  : _("Summary message followed by the original message"),    91             "summary-only"          : _("Summary message only"),    92             "summary-wraps-message" : _("Summary message wrapping the original message"),    93                                   },    94         "organiser_replacement" : {    95             "any"                   : _("Anyone"),    96             "attendee"              : _("Existing attendees only"),    97             "never"                 : _("Never allow organiser replacement"),    98                                   },    99         "participating"         : {   100             "participate"           : _("Participate"),   101             "no"                    : _("Do not participate"),   102                                   }   103         }   104    105     def __init__(self, user, store_dir=None):   106         FileBase.__init__(self, store_dir or config.PREFERENCES_DIR)   107         self.user = user   108    109     def get(self, name, default=None, config_default=False):   110    111         """   112         Return the value for 'name', with absent entries providing a default of   113         None or any indicated 'default' or, if 'config_default' is set to a true   114         value, the default value from the config module.   115         """   116    117         try:   118             return self[name]   119         except KeyError:   120             if config_default:   121                 return self.known_keys.get(name, default)   122             else:   123                 return default   124    125     def get_all(self, names):   126    127         """   128         Return a dictionary containing values for entries having the given   129         'names'. Absent entries for names are omitted without error.   130         """   131    132         d = {}   133         for name in names:   134             value = self.get(name)   135             if value is not None:   136                 d[name] = value   137         return d   138    139     def has_key(self, name):   140    141         "Return whether an entry exists for 'name'."   142    143         try:   144             self[name]   145             return True   146         except KeyError:   147             return False   148    149     def keys(self):   150    151         "Return all entry names in the preferences."   152    153         filename = self.get_object_in_store(self.user)   154         if not filename or not isdir(filename):   155             return []   156    157         return listdir(filename)   158    159     def items(self, all_known=False, default=None, config_default=False):   160    161         """   162         Return all entries in the preferences or all known entries if   163         'all_known' is set to a true value, with absent entries providing a   164         default of None or any indicated 'default' or, if 'config_default' is   165         set to a true value, the default value from the config module.   166    167         Each entry will have the form (key, value).   168         """   169    170         l = []   171         for key in (all_known and self.known_keys or self).keys():   172             l.append((key, self.get(key, default, config_default)))   173         return l   174    175     def choices(self, all_known=False, default=None, config_default=False):   176    177         """   178         Return all entries in the preferences or all known entries if   179         'all_known' is set to a true value, with absent entries providing a   180         default of None or any indicated 'default' or, if 'config_default' is   181         set to a true value, the default value from the config module.   182    183         Each entry will have the form (key, value, choices).   184         """   185    186         l = []   187         for key, value in self.items(all_known, default, config_default):   188             l.append((key, value, self.known_key_choices.get(key)))   189         return l   190    191     def __getitem__(self, name):   192    193         "Return the value for 'name', raising a KeyError if absent."   194    195         filename = self.get_object_in_store(self.user, name)   196         if not filename or not exists(filename):   197             raise KeyError, name   198    199         f = codecs.open(filename, encoding="utf-8")   200         try:   201             return f.read().strip()   202         finally:   203             f.close()   204    205     def __setitem__(self, name, value):   206    207         "Set for 'name' the given 'value'."   208    209         filename = self.get_object_in_store(self.user, name)   210         if not filename:   211             return False   212    213         f = codecs.open(filename, "w", encoding="utf-8")   214         try:   215             f.write(value)   216         finally:   217             f.close()   218             fix_permissions(filename)   219    220         return True   221    222 # vim: tabstop=4 expandtab shiftwidth=4