1.1 --- a/imiptools/period.py Sun Mar 06 00:46:26 2016 +0100
1.2 +++ b/imiptools/period.py Sun Mar 06 19:19:23 2016 +0100
1.3 @@ -458,6 +458,19 @@
1.4
1.5 "Common operations on free/busy period collections."
1.6
1.7 + def __init__(self, mutable=True):
1.8 + self.mutable = mutable
1.9 +
1.10 + def _check_mutable(self):
1.11 + if not self.mutable:
1.12 + raise TypeError, "Cannot mutate this collection."
1.13 +
1.14 + def copy(self):
1.15 +
1.16 + "Make an independent mutable copy of the collection."
1.17 +
1.18 + return FreeBusyCollection(list(self), True)
1.19 +
1.20 # List emulation methods.
1.21
1.22 def __iadd__(self, other):
1.23 @@ -524,6 +537,8 @@
1.24 using the given 'replacements'.
1.25 """
1.26
1.27 + self._check_mutable()
1.28 +
1.29 self.remove_overlapping(period)
1.30 for replacement in replacements:
1.31 self.insert_period(replacement)
1.32 @@ -599,6 +614,8 @@
1.33 free/busy offer.
1.34 """
1.35
1.36 + self._check_mutable()
1.37 +
1.38 self.remove_event_periods(uid, recurrenceid)
1.39
1.40 for p in periods:
1.41 @@ -608,13 +625,14 @@
1.42
1.43 "An abstraction for a collection of free/busy periods."
1.44
1.45 - def __init__(self, periods=None):
1.46 + def __init__(self, periods=None, mutable=True):
1.47
1.48 """
1.49 Initialise the collection with the given list of 'periods', or start an
1.50 empty collection if no list is given.
1.51 """
1.52
1.53 + FreeBusyCollectionBase.__init__(self, mutable)
1.54 self.periods = periods or []
1.55
1.56 # List emulation methods.
1.57 @@ -637,6 +655,8 @@
1.58
1.59 "Insert the given 'period' into the collection."
1.60
1.61 + self._check_mutable()
1.62 +
1.63 i = bisect_left(self.periods, period)
1.64 if i == len(self.periods):
1.65 self.periods.append(period)
1.66 @@ -647,6 +667,8 @@
1.67
1.68 "Remove the given 'periods' from the collection."
1.69
1.70 + self._check_mutable()
1.71 +
1.72 for period in periods:
1.73 i = bisect_left(self.periods, period)
1.74 if i < len(self.periods) and self.periods[i] == period:
1.75 @@ -662,6 +684,8 @@
1.76 Return the removed periods.
1.77 """
1.78
1.79 + self._check_mutable()
1.80 +
1.81 removed = []
1.82 i = 0
1.83 while i < len(self.periods):
1.84 @@ -686,6 +710,8 @@
1.85 Return the removed periods.
1.86 """
1.87
1.88 + self._check_mutable()
1.89 +
1.90 removed = []
1.91 i = 0
1.92 while i < len(self.periods):
1.93 @@ -713,6 +739,8 @@
1.94 Return any removed period in a list.
1.95 """
1.96
1.97 + self._check_mutable()
1.98 +
1.99 removed = []
1.100
1.101 search = Period(start, start)
1.102 @@ -787,6 +815,8 @@
1.103
1.104 "Remove all periods overlapping with 'period' from the collection."
1.105
1.106 + self._check_mutable()
1.107 +
1.108 overlapping = self.get_overlapping(period)
1.109
1.110 if overlapping:
1.111 @@ -800,12 +830,13 @@
1.112 system.
1.113 """
1.114
1.115 - def __init__(self, cursor, table_name):
1.116 + def __init__(self, cursor, table_name, mutable=True):
1.117
1.118 """
1.119 Initialise the collection with the given 'cursor' and 'table_name'.
1.120 """
1.121
1.122 + FreeBusyCollectionBase.__init__(self, mutable)
1.123 self.cursor = cursor
1.124 self.table_name = table_name
1.125
1.126 @@ -857,6 +888,8 @@
1.127
1.128 "Insert the given 'period' into the collection."
1.129
1.130 + self._check_mutable()
1.131 +
1.132 values = period.as_tuple(strings_only=True)
1.133 query = "insert into %(table)s values (%(columns)s)" % {
1.134 "table" : self.table_name,
1.135 @@ -868,6 +901,8 @@
1.136
1.137 "Remove the given 'periods' from the collection."
1.138
1.139 + self._check_mutable()
1.140 +
1.141 for period in periods:
1.142 values = period.as_tuple(strings_only=True)
1.143 query = """\
1.144 @@ -886,6 +921,8 @@
1.145 Return the removed periods.
1.146 """
1.147
1.148 + self._check_mutable()
1.149 +
1.150 if recurrenceid:
1.151 condition = "where uid = ? and recurrenceid = ?"
1.152 values = (uid, recurrenceid)
1.153 @@ -920,6 +957,8 @@
1.154 Return the removed periods.
1.155 """
1.156
1.157 + self._check_mutable()
1.158 +
1.159 if recurrenceids is None:
1.160 condition = "where uid = ? and recurrenceid is not null"
1.161 values = (uid,)
1.162 @@ -954,6 +993,8 @@
1.163 Return any removed period in a list.
1.164 """
1.165
1.166 + self._check_mutable()
1.167 +
1.168 condition = "where uid = ? and start = ? and recurrenceid is null"
1.169 values = (uid, start)
1.170
1.171 @@ -1024,6 +1065,8 @@
1.172
1.173 "Remove all periods overlapping with 'period' from the collection."
1.174
1.175 + self._check_mutable()
1.176 +
1.177 condition = "where start < ? and end > ?"
1.178 values = (format_datetime(period.get_end_point()), format_datetime(period.get_start_point()))
1.179