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

Source Code for Module dns.node

  1  # Copyright (C) 2001-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  """DNS nodes.  A node is a set of rdatasets.""" 
 17   
 18  import StringIO 
 19   
 20  import dns.rdataset 
 21  import dns.rdatatype 
 22  import dns.renderer 
 23   
24 -class Node(object):
25 """A DNS node. 26 27 A node is a set of rdatasets 28 29 @ivar rdatasets: the node's rdatasets 30 @type rdatasets: list of dns.rdataset.Rdataset objects""" 31 32 __slots__ = ['rdatasets'] 33
34 - def __init__(self):
35 """Initialize a DNS node. 36 """ 37 38 self.rdatasets = [];
39
40 - def to_text(self, name, **kw):
41 """Convert a node to text format. 42 43 Each rdataset at the node is printed. Any keyword arguments 44 to this method are passed on to the rdataset's to_text() method. 45 @param name: the owner name of the rdatasets 46 @type name: dns.name.Name object 47 @rtype: string 48 """ 49 50 s = StringIO.StringIO() 51 for rds in self.rdatasets: 52 if len(rds) > 0: 53 print >> s, rds.to_text(name, **kw) 54 return s.getvalue()[:-1]
55
56 - def __repr__(self):
57 return '<DNS node ' + str(id(self)) + '>'
58
59 - def __eq__(self, other):
60 """Two nodes are equal if they have the same rdatasets. 61 62 @rtype: bool 63 """ 64 # 65 # This is inefficient. Good thing we don't need to do it much. 66 # 67 for rd in self.rdatasets: 68 if rd not in other.rdatasets: 69 return False 70 for rd in other.rdatasets: 71 if rd not in self.rdatasets: 72 return False 73 return True
74
75 - def __ne__(self, other):
76 return not self.__eq__(other)
77
78 - def __len__(self):
79 return len(self.rdatasets)
80
81 - def __iter__(self):
82 return iter(self.rdatasets)
83
84 - def find_rdataset(self, rdclass, rdtype, covers=dns.rdatatype.NONE, 85 create=False):
86 """Find an rdataset matching the specified properties in the 87 current node. 88 89 @param rdclass: The class of the rdataset 90 @type rdclass: int 91 @param rdtype: The type of the rdataset 92 @type rdtype: int 93 @param covers: The covered type. Usually this value is 94 dns.rdatatype.NONE, but if the rdtype is dns.rdatatype.SIG or 95 dns.rdatatype.RRSIG, then the covers value will be the rdata 96 type the SIG/RRSIG covers. The library treats the SIG and RRSIG 97 types as if they were a family of 98 types, e.g. RRSIG(A), RRSIG(NS), RRSIG(SOA). This makes RRSIGs much 99 easier to work with than if RRSIGs covering different rdata 100 types were aggregated into a single RRSIG rdataset. 101 @type covers: int 102 @param create: If True, create the rdataset if it is not found. 103 @type create: bool 104 @raises KeyError: An rdataset of the desired type and class does 105 not exist and I{create} is not True. 106 @rtype: dns.rdataset.Rdataset object 107 """ 108 109 for rds in self.rdatasets: 110 if rds.match(rdclass, rdtype, covers): 111 return rds 112 if not create: 113 raise KeyError 114 rds = dns.rdataset.Rdataset(rdclass, rdtype) 115 self.rdatasets.append(rds) 116 return rds
117
118 - def get_rdataset(self, rdclass, rdtype, covers=dns.rdatatype.NONE, 119 create=False):
120 """Get an rdataset matching the specified properties in the 121 current node. 122 123 None is returned if an rdataset of the specified type and 124 class does not exist and I{create} is not True. 125 126 @param rdclass: The class of the rdataset 127 @type rdclass: int 128 @param rdtype: The type of the rdataset 129 @type rdtype: int 130 @param covers: The covered type. 131 @type covers: int 132 @param create: If True, create the rdataset if it is not found. 133 @type create: bool 134 @rtype: dns.rdataset.Rdataset object or None 135 """ 136 137 try: 138 rds = self.find_rdataset(rdclass, rdtype, covers, create) 139 except KeyError: 140 rds = None 141 return rds
142
143 - def delete_rdataset(self, rdclass, rdtype, covers=dns.rdatatype.NONE):
144 """Delete the rdataset matching the specified properties in the 145 current node. 146 147 If a matching rdataset does not exist, it is not an error. 148 149 @param rdclass: The class of the rdataset 150 @type rdclass: int 151 @param rdtype: The type of the rdataset 152 @type rdtype: int 153 @param covers: The covered type. 154 @type covers: int 155 """ 156 157 rds = self.get_rdataset(rdclass, rdtype, covers) 158 if not rds is None: 159 self.rdatasets.remove(rds)
160
161 - def replace_rdataset(self, replacement):
162 """Replace an rdataset. 163 164 It is not an error if there is no rdataset matching I{replacement}. 165 166 Ownership of the I{replacement} object is transferred to the node; 167 in other words, this method does not store a copy of I{replacement} 168 at the node, it stores I{replacement} itself. 169 """ 170 171 if not isinstance(replacement, dns.rdataset.Rdataset): 172 raise ValueError, 'replacement is not an rdataset' 173 self.delete_rdataset(replacement.rdclass, replacement.rdtype, 174 replacement.covers) 175 self.rdatasets.append(replacement)
176