1 # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
3 # Permission to use, copy, modify, and distribute this software and its
4 # documentation for any purpose with or without fee is hereby granted,
5 # provided that the above copyright notice and this permission notice
6 # appear in all copies.
8 # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
9 # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
11 # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
14 # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 """A simple Set class."""
19 """A simple set class.
21 Sets are not in Python until 2.3, and rdata are not immutable so
22 we cannot use sets.Set anyway. This class implements subset of
23 the 2.3 Set interface using a list as the container.
25 @ivar items: A list of the items which are in the set
30 def __init__(self
, items
=None):
31 """Initialize the set.
33 @param items: the initial set of items
34 @type items: any iterable or None
43 return "dns.simpleset.Set(%s)" % repr(self
.items
)
46 """Add an item to the set."""
47 if not item
in self
.items
:
48 self
.items
.append(item
)
50 def remove(self
, item
):
51 """Remove an item from the set."""
52 self
.items
.remove(item
)
54 def discard(self
, item
):
55 """Remove an item from the set if present."""
57 self
.items
.remove(item
)
62 """Make a (shallow) copy of the set.
64 There is a 'clone protocol' that subclasses of this class
65 should use. To make a copy, first call your super's _clone()
66 method, and use the object returned as the new instance. Then
67 make shallow copies of the attributes defined in the subclass.
69 This protocol allows us to write the set algorithms that
70 return new instances (e.g. union) once, and keep using them in
75 obj
= cls
.__new
__(cls
)
76 obj
.items
= list(self
.items
)
80 """Make a (shallow) copy of the set."""
84 """Make a (shallow) copy of the set."""
87 def union_update(self
, other
):
88 """Update the set, adding any elements from other which are not
90 @param other: the collection of items with which to update the set
91 @type other: Set object
93 if not isinstance(other
, Set
):
94 raise ValueError('other must be a Set instance')
97 for item
in other
.items
:
100 def intersection_update(self
, other
):
101 """Update the set, removing any elements from other which are not
103 @param other: the collection of items with which to update the set
104 @type other: Set object
106 if not isinstance(other
, Set
):
107 raise ValueError('other must be a Set instance')
110 # we make a copy of the list so that we can remove items from
111 # the list without breaking the iterator.
112 for item
in list(self
.items
):
113 if item
not in other
.items
:
114 self
.items
.remove(item
)
116 def difference_update(self
, other
):
117 """Update the set, removing any elements from other which are in
119 @param other: the collection of items with which to update the set
120 @type other: Set object
122 if not isinstance(other
, Set
):
123 raise ValueError('other must be a Set instance')
127 for item
in other
.items
:
130 def union(self
, other
):
131 """Return a new set which is the union of I{self} and I{other}.
133 @param other: the other set
134 @type other: Set object
135 @rtype: the same type as I{self}
139 obj
.union_update(other
)
142 def intersection(self
, other
):
143 """Return a new set which is the intersection of I{self} and I{other}.
145 @param other: the other set
146 @type other: Set object
147 @rtype: the same type as I{self}
151 obj
.intersection_update(other
)
154 def difference(self
, other
):
155 """Return a new set which I{self} - I{other}, i.e. the items
156 in I{self} which are not also in I{other}.
158 @param other: the other set
159 @type other: Set object
160 @rtype: the same type as I{self}
164 obj
.difference_update(other
)
167 def __or__(self
, other
):
168 return self
.union(other
)
170 def __and__(self
, other
):
171 return self
.intersection(other
)
173 def __add__(self
, other
):
174 return self
.union(other
)
176 def __sub__(self
, other
):
177 return self
.difference(other
)
179 def __ior__(self
, other
):
180 self
.union_update(other
)
183 def __iand__(self
, other
):
184 self
.intersection_update(other
)
187 def __iadd__(self
, other
):
188 self
.union_update(other
)
191 def __isub__(self
, other
):
192 self
.difference_update(other
)
195 def update(self
, other
):
196 """Update the set, adding any elements from other which are not
198 @param other: the collection of items with which to update the set
199 @type other: any iterable type"""
204 """Make the set empty."""
207 def __eq__(self
, other
):
208 # Yes, this is inefficient but the sets we're dealing with are
209 # usually quite small, so it shouldn't hurt too much.
210 for item
in self
.items
:
211 if not item
in other
.items
:
213 for item
in other
.items
:
214 if not item
in self
.items
:
218 def __ne__(self
, other
):
219 return not self
.__eq
__(other
)
222 return len(self
.items
)
225 return iter(self
.items
)
227 def __getitem__(self
, i
):
230 def __delitem__(self
, i
):
233 def __getslice__(self
, i
, j
):
234 return self
.items
[i
:j
]
236 def __delslice__(self
, i
, j
):
239 def issubset(self
, other
):
240 """Is I{self} a subset of I{other}?
245 if not isinstance(other
, Set
):
246 raise ValueError('other must be a Set instance')
247 for item
in self
.items
:
248 if not item
in other
.items
:
252 def issuperset(self
, other
):
253 """Is I{self} a superset of I{other}?
258 if not isinstance(other
, Set
):
259 raise ValueError('other must be a Set instance')
260 for item
in other
.items
:
261 if not item
in self
.items
: