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

# Source Code for Module dns.set

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