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