Package dns :: Module set |
[hide private]
[frames] | no frames]

# Source Code for Module dns.set

      1  # Copyright (C) 2003-2007, 2009, 2010 Nominum, Inc.
      2  #
      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.
      7  #
      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.
     15
     16  """A simple Set class."""
     17
     18 -class Set(object):
     19      """A simple set class.
     20
     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.
     24
     25      @ivar items: A list of the items which are in the set
     26      @type items: list"""
     27
     28      __slots__ = ['items']
     29
     30 -    def __init__(self, items=None):
     31          """Initialize the set.
     32
     33          @param items: the initial set of items
     34          @type items: any iterable or None
     35          """
     36
     37          self.items = []
     38          if not items is None:
     39              for item in items:
     40                  self.add(item)
     41
     42 -    def __repr__(self):
     43          return "dns.simpleset.Set(%s)" % repr(self.items)
     44
     45 -    def add(self, item):
     46          """Add an item to the set."""
     47          if not item in self.items:
     48              self.items.append(item)
     49
     50 -    def remove(self, item):
     51          """Remove an item from the set."""
     52          self.items.remove(item)
     53
     54 -    def discard(self, item):
     55          """Remove an item from the set if present."""
     56          try:
     57              self.items.remove(item)
     58          except ValueError:
     59              pass
     60
     61 -    def _clone(self):
     62          """Make a (shallow) copy of the set.
     63
     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.
     68
     69          This protocol allows us to write the set algorithms that
     70          return new instances (e.g. union) once, and keep using them in
     71          subclasses.
     72          """
     73
     74          cls = self.__class__
     75          obj = cls.__new__(cls)
     76          obj.items = list(self.items)
     77          return obj
     78
     79 -    def __copy__(self):
     80          """Make a (shallow) copy of the set."""
     81          return self._clone()
     82
     83 -    def copy(self):
     84          """Make a (shallow) copy of the set."""
     85          return self._clone()
     86
     87 -    def union_update(self, other):
     88          """Update the set, adding any elements from other which are not
     89          already in the set.
     90          @param other: the collection of items with which to update the set
     91          @type other: Set object
     92          """
     93          if not isinstance(other, Set):
     94              raise ValueError('other must be a Set instance')
     95          if self is other:
     96              return
     97          for item in other.items:
     98              self.add(item)
     99
    100 -    def intersection_update(self, other):
    101          """Update the set, removing any elements from other which are not
    102          in both sets.
    103          @param other: the collection of items with which to update the set
    104          @type other: Set object
    105          """
    106          if not isinstance(other, Set):
    107              raise ValueError('other must be a Set instance')
    108          if self is other:
    109              return
    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)
    115
    116 -    def difference_update(self, other):
    117          """Update the set, removing any elements from other which are in
    118          the set.
    119          @param other: the collection of items with which to update the set
    120          @type other: Set object
    121          """
    122          if not isinstance(other, Set):
    123              raise ValueError('other must be a Set instance')
    124          if self is other:
    125              self.items = []
    126          else:
    127              for item in other.items:
    128                  self.discard(item)
    129
    130 -    def union(self, other):
    131          """Return a new set which is the union of I{self} and I{other}.
    132
    133          @param other: the other set
    134          @type other: Set object
    135          @rtype: the same type as I{self}
    136          """
    137
    138          obj = self._clone()
    139          obj.union_update(other)
    140          return obj
    141
    142 -    def intersection(self, other):
    143          """Return a new set which is the intersection of I{self} and I{other}.
    144
    145          @param other: the other set
    146          @type other: Set object
    147          @rtype: the same type as I{self}
    148          """
    149
    150          obj = self._clone()
    151          obj.intersection_update(other)
    152          return obj
    153
    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}.
    157
    158          @param other: the other set
    159          @type other: Set object
    160          @rtype: the same type as I{self}
    161          """
    162
    163          obj = self._clone()
    164          obj.difference_update(other)
    165          return obj
    166
    167 -    def __or__(self, other):
    168          return self.union(other)
    169
    170 -    def __and__(self, other):
    171          return self.intersection(other)
    172
    173 -    def __add__(self, other):
    174          return self.union(other)
    175
    176 -    def __sub__(self, other):
    177          return self.difference(other)
    178
    179 -    def __ior__(self, other):
    180          self.union_update(other)
    181          return self
    182
    183 -    def __iand__(self, other):
    184          self.intersection_update(other)
    185          return self
    186
    187 -    def __iadd__(self, other):
    188          self.union_update(other)
    189          return self
    190
    191 -    def __isub__(self, other):
    192          self.difference_update(other)
    193          return self
    194
    195 -    def update(self, other):
    196          """Update the set, adding any elements from other which are not
    197          already in the set.
    198          @param other: the collection of items with which to update the set
    199          @type other: any iterable type"""
    200          for item in other:
    201              self.add(item)
    202
    203 -    def clear(self):
    204          """Make the set empty."""
    205          self.items = []
    206
    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:
    212                  return False
    213          for item in other.items:
    214              if not item in self.items:
    215                  return False
    216          return True
    217
    218 -    def __ne__(self, other):
    219          return not self.__eq__(other)
    220
    221 -    def __len__(self):
    222          return len(self.items)
    223
    224 -    def __iter__(self):
    225          return iter(self.items)
    226
    227 -    def __getitem__(self, i):
    228          return self.items[i]
    229
    230 -    def __delitem__(self, i):
    231          del self.items[i]
    232
    233 -    def __getslice__(self, i, j):
    234          return self.items[i:j]
    235
    236 -    def __delslice__(self, i, j):
    237          del self.items[i:j]
    238
    239 -    def issubset(self, other):
    240          """Is I{self} a subset of I{other}?
    241
    242          @rtype: bool
    243          """
    244
    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:
    249                  return False
    250          return True
    251
    252 -    def issuperset(self, other):
    253          """Is I{self} a superset of I{other}?
    254
    255          @rtype: bool
    256          """
    257
    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:
    262                  return False
    263          return True
    264