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"""DNS name dictionary""" 17 18import dns.name 19 20class NameDict(dict): 21 22 """A dictionary whose keys are dns.name.Name objects. 23 @ivar max_depth: the maximum depth of the keys that have ever been 24 added to the dictionary. 25 @type max_depth: int 26 """ 27 28 def __init__(self, *args, **kwargs): 29 super(NameDict, self).__init__(*args, **kwargs) 30 self.max_depth = 0 31 32 def __setitem__(self, key, value): 33 if not isinstance(key, dns.name.Name): 34 raise ValueError('NameDict key must be a name') 35 depth = len(key) 36 if depth > self.max_depth: 37 self.max_depth = depth 38 super(NameDict, self).__setitem__(key, value) 39 40 def get_deepest_match(self, name): 41 """Find the deepest match to I{name} in the dictionary. 42 43 The deepest match is the longest name in the dictionary which is 44 a superdomain of I{name}. 45 46 @param name: the name 47 @type name: dns.name.Name object 48 @rtype: (key, value) tuple 49 """ 50 51 depth = len(name) 52 if depth > self.max_depth: 53 depth = self.max_depth 54 for i in xrange(-depth, 0): 55 n = dns.name.Name(name[i:]) 56 if self.has_key(n): 57 return (n, self[n]) 58 v = self[dns.name.empty] 59 return (dns.name.empty, v) 60