Codebase list dnspython / e52d038
Imported Upstream version 1.3.5 SVN-Git Migration 8 years ago
27 changed file(s) with 287 addition(s) and 43 deletion(s). Raw diff Collapse all Expand all
0 2005-07-31 Bob Halley <halley@nominum.com>
0 2005-10-31 Bob Halley <halley@dnspython.org>
1
2 * (Version 1.3.5 released)
3
4 2005-10-12 Bob Halley <halley@dnspython.org>
5
6 * dns/zone.py: Zone.iterate_rdatasets() and Zone.iterate_rdatas()
7 did not have a default rdtype of dns.rdatatype.ANY as their
8 docstrings said they did. They do now.
9
10 2005-10-06 Bob Halley <halley@dnspython.org>
11
12 * dns/name.py: Added the parent() method, which returns the
13 parent of a name.
14
15 2005-10-01 Bob Halley <halley@dnspython.org>
16
17 * dns/resolver.py: Added zone_for_name() helper, which returns
18 the name of the zone which contains the specified name.
19
20 * dns/resolver.py: Added get_default_resolver(), which returns
21 the default resolver, initializing it if necessary.
22
23 2005-09-29 Bob Halley <halley@dnspython.org>
24
25 * dns/resolver.py (Resolver._compute_timeout): If time goes
26 backwards a little bit, ignore it.
27
28 2005-07-31 Bob Halley <halley@dnspython.org>
129
230 * (Version 1.3.4 released)
331
00 Metadata-Version: 1.0
11 Name: dnspython
2 Version: 1.3.4
2 Version: 1.3.5
33 Summary: DNS toolkit
44 Home-page: http://www.dnspython.org
55 Author: Bob Halley
2121
2222 ABOUT THIS RELEASE
2323
24 This is dnspython 1.3.4
24 This is dnspython 1.3.5
25
26 New since 1.3.4:
27
28 In the resolver, if time goes backward a little bit, ignore
29 it.
30
31 zone_for_name() has been added to the resolver module. It
32 returns the zone which is authoritative for the specified
33 name, which is handy for dynamic update. E.g.
34
35 import dns.resolver
36 print dns.resolver.zone_for_name('www.dnspython.org')
37
38 will output "dnspython.org." and
39
40 print dns.resolver.zone_for_name('a.b.c.d.e.f.example.')
41
42 will output ".".
43
44 The default resolver can be fetched with the
45 get_default_resolver() method.
46
47 You can now get the parent (immediate superdomain) of a name
48 by using the parent() method.
49
50 Zone.iterate_rdatasets() and Zone.iterate_rdatas() now have
51 a default rdtype of dns.rdatatype.ANY like the documentation
52 says.
53
54 A Dynamic DNS example, ddns.py, has been added.
2555
2656 New since 1.3.3:
2757
5151 #
5252 best_start = 0
5353 best_len = 0
54 start = -1
5455 last_was_zero = False
5556 for i in xrange(8):
5657 if chunks[i] != '0':
1616
1717 import cStringIO
1818 import random
19 import string
2019 import struct
2120 import sys
2221 import time
2424 import string
2525 import struct
2626 import sys
27 import types
2827
2928 import dns.exception
3029
6665 class AbsoluteConcatenation(dns.exception.DNSException):
6766 """Raised if an attempt is made to append anything other than the
6867 empty name to an absolute name."""
68 pass
69
70 class NoParent(dns.exception.DNSException):
71 """Raised if an attempt is made to get the parent of the root name
72 or the empty name."""
6973 pass
7074
7175 _escaped = {
489493 return self.derelativize(origin)
490494 else:
491495 return self
496
497 def parent(self):
498 """Return the parent of the name.
499 @rtype: dns.name.Name object
500 @raises NoParent: the name is either the root name or the empty name,
501 and thus has no parent.
502 """
503 if self == root or self == empty:
504 raise NoParent
505 return Name(self.labels[1:])
492506
493507 root = Name([''])
494508 empty = Name([])
505519 labels = []
506520 label = ''
507521 escaping = False
522 edigits = 0
523 total = 0
508524 if text == '@':
509525 text = ''
510526 if text:
8585 @type source: string
8686 @param source_port: The port from which to send the message.
8787 The default is 0.
88 @type port: int"""
88 @type source_port: int"""
8989
9090 wire = q.to_wire()
9191 if af is None:
178178 @type source: string
179179 @param source_port: The port from which to send the message.
180180 The default is 0.
181 @type port: int"""
181 @type source_port: int"""
182182
183183 wire = q.to_wire()
184184 if af is None:
244244 @param keyname: The name of the TSIG key to use
245245 @type keyname: dns.name.Name object or string
246246 @param relativize: If True, all names in the zone will be relativized to
247 the zone origin.
247 the zone origin. It is essential that the relativize setting matches
248 the one specified to dns.zone.from_xfr().
248249 @type relativize: bool
249250 @param af: the address family to use. The default is None, which
250251 causes the address family to use to be inferred from the form of of where.
259260 @type source: string
260261 @param source_port: The port from which to send the message.
261262 The default is 0.
262 @type port: int"""
263 @type source_port: int"""
263264
264265 if isinstance(zone, str):
265266 zone = dns.name.from_text(zone)
2424 chunk of hexstring that _hexify() produces before whitespace occurs.
2525 @type _hex_chunk: int"""
2626
27 import codecs
28 import cStringIO
29
3027 import dns.exception
3128 import dns.rdataclass
3229 import dns.rdatatype
249246 @param origin: The origin to use for relative names
250247 @type origin: dns.name.Name
251248 @param relativize: should names be relativized?
252 @type origin: bool
249 @type relativize: bool
253250 @rtype: dns.rdata.Rdata instance
254251 """
255252
1717 import random
1818 import StringIO
1919 import struct
20 import sys
2120
2221 import dns.exception
2322 import dns.rdatatype
1313 # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1414
1515 import cStringIO
16 import math
1716 import struct
1817
1918 import dns.exception
1313 # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1414
1515 import cStringIO
16 import struct
1716
1817 import dns.exception
1918 import dns.rdata
1111 # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1212 # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
1313 # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14
15 import struct
1614
1715 import dns.exception
1816 import dns.rdata
1111 # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1212 # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
1313 # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14
15 import struct
1614
1715 import dns.exception
1816 import dns.rdata
1111 # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1212 # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
1313 # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14
15 import socket
1614
1715 import dns.exception
1816 import dns.rdata
1111 # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1212 # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
1313 # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14
15 import socket
1614
1715 import dns.exception
1816 import dns.ipv4
1111 # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1212 # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
1313 # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14
15 import socket
1614
1715 import dns.exception
1816 import dns.inet
1313 # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1414
1515 import cStringIO
16 import socket
1716 import struct
1817
1918 import dns.exception
1111 # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1212 # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
1313 # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14
15 import socket
1614
1715 import dns.exception
1816 import dns.rdata
1313 # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1414
1515 """NS-like base classes."""
16
17 import struct
1816
1917 import dns.exception
2018 import dns.rdata
2020 import socket
2121 import sys
2222 import time
23 import types
2423
2524 import dns.exception
2625 import dns.message
5049 class NoNameservers(dns.exception.DNSException):
5150 """No non-broken nameservers are available to answer the query."""
5251 pass
52
53 class NotAbsolute(dns.exception.DNSException):
54 """Raised if an absolute domain name is required but a relative name
55 was provided."""
56 pass
57
58 class NoRootSOA(dns.exception.DNSException):
59 """Raised if for some reason there is no SOA at the root name.
60 This should never happen!"""
61 pass
62
5363
5464 class Answer(object):
5565 """DNS stub resolver answer
426436 def _compute_timeout(self, start):
427437 now = time.time()
428438 if now < start:
429 # Time going backwards is bad. Just give up.
430 raise Timeout
439 if start - now > 1:
440 # Time going backwards is bad. Just give up.
441 raise Timeout
442 else:
443 # Time went backwards, but only a little. This can
444 # happen, e.g. under vmware with older linux kernels.
445 # Pretend it didn't happen.
446 now = start
431447 duration = now - start
432448 if duration >= self.lifetime:
433449 raise Timeout
595611
596612 default_resolver = None
597613
614 def get_default_resolver():
615 """Get the default resolver, initializing it if necessary."""
616 global default_resolver
617 if default_resolver is None:
618 default_resolver = Resolver()
619 return default_resolver
620
598621 def query(qname, rdtype=dns.rdatatype.A, rdclass=dns.rdataclass.IN,
599622 tcp=False):
600623 """Query nameservers to find the answer to the question.
603626 object to make the query.
604627 @see: L{dns.resolver.Resolver.query} for more information on the
605628 parameters."""
606 global default_resolver
607 if default_resolver is None:
608 default_resolver = Resolver()
609 return default_resolver.query(qname, rdtype, rdclass, tcp)
629 return get_default_resolver().query(qname, rdtype, rdclass, tcp)
630
631 def zone_for_name(name, rdclass=dns.rdataclass.IN, tcp=False, resolver=None):
632 """Find the name of the zone which contains the specified name.
633
634 @param name: the query name
635 @type name: absolute dns.name.Name object or string
636 @param rdclass: The query class
637 @type rdclass: int
638 @param tcp: use TCP to make the query (default is False).
639 @type tcp: bool
640 @param resolver: the resolver to use
641 @type resolver: dns.resolver.Resolver object or None
642 @rtype: dns.name.Name"""
643
644 if isinstance(name, str):
645 name = dns.name.from_text(name, dns.name.root)
646 if resolver is None:
647 resolver = get_default_resolver()
648 if not name.is_absolute():
649 raise NotAbsolute, name
650 while 1:
651 try:
652 answer = resolver.query(name, dns.rdatatype.SOA, rdclass, tcp)
653 return name
654 except (dns.resolver.NXDOMAIN, dns.resolver.NoAnswer):
655 try:
656 name = name.parent()
657 except dns.name.NoParent:
658 raise NoRootSOA
1616
1717 MAJOR = 1
1818 MINOR = 3
19 MICRO = 4
19 MICRO = 5
2020 RELEASELEVEL = 0x0f
2121 SERIAL = 0
2222
402402 rrset = None
403403 return rrset
404404
405 def iterate_rdatasets(self, rdtype=None, covers=dns.rdatatype.NONE):
405 def iterate_rdatasets(self, rdtype=dns.rdatatype.ANY,
406 covers=dns.rdatatype.NONE):
406407 """Return a generator which yields (name, rdataset) tuples for
407408 all rdatasets in the zone which have the specified I{rdtype}
408409 and I{covers}. If I{rdtype} is dns.rdatatype.ANY, the default,
424425 (rds.rdtype == rdtype and rds.covers == covers):
425426 yield (name, rds)
426427
427 def iterate_rdatas(self, rdtype=None, covers=dns.rdatatype.NONE):
428 def iterate_rdatas(self, rdtype=dns.rdatatype.ANY,
429 covers=dns.rdatatype.NONE):
428430 """Return a generator which yields (name, ttl, rdata) tuples for
429431 all rdatas in the zone which have the specified I{rdtype}
430432 and I{covers}. If I{rdtype} is dns.rdatatype.ANY, the default,
803805
804806 @param xfr: The xfr generator
805807 @type xfr: generator of dns.message.Message objects
806 @param relativize: should names be relativized? The default is True
808 @param relativize: should names be relativized? The default is True.
809 It is essential that the relativize setting matches the one specified
810 to dns.query.xfr().
807811 @type relativize: bool
808812 @raises dns.zone.NoSOA: No SOA RR was found at the zone origin
809813 @raises dns.zone.NoNS: No NS RRset was found at the zone origin
0 #!/usr/bin/env python
1
2 #
3 # Use a TSIG-signed DDNS update to update our hostname-to-address
4 # mapping.
5 #
6 # usage: ddns.py <ip-address>
7 #
8 # On linux systems, you can automatically update your DNS any time an
9 # interface comes up by adding an ifup-local script that invokes this
10 # python code.
11 #
12 # E.g. on my systems I have this
13 #
14 # #!/bin/sh
15 #
16 # DEVICE=$1
17 #
18 # if [ "X${DEVICE}" == "Xeth0" ]; then
19 # IPADDR=`LANG= LC_ALL= ifconfig ${DEVICE} | grep 'inet addr' |
20 # awk -F: '{ print $2 } ' | awk '{ print $1 }'`
21 # /usr/local/sbin/ddns.py $IPADDR
22 # fi
23 #
24 # in /etc/ifup-local.
25 #
26
27 import sys
28
29 import dns.update
30 import dns.query
31 import dns.tsigkeyring
32
33 #
34 # Replace the keyname and secret with appropriate values for your
35 # configuration.
36 #
37 keyring = dns.tsigkeyring.from_text({
38 'keyname.' : 'NjHwPsMKjdN++dOfE5iAiQ=='
39 })
40
41 #
42 # Replace "example." with your domain, and "host" with your hostname.
43 #
44 update = dns.update.Update('example.', keyring=keyring)
45 update.replace('host', 300, 'A', sys.argv[1])
46
47 #
48 # Replace "10.0.0.1" with the IP address of your master server.
49 #
50 response = dns.query.tcp(update, '10.0.0.1', timeout=10)
1818
1919 setup(
2020 name = "dnspython",
21 version = "1.3.4",
21 version = "1.3.5",
2222 description = "DNS toolkit",
2323 long_description = \
2424 """dnspython is a DNS toolkit for Python. It supports almost all
588588 (n, cused) = dns.name.from_wire(w, 0)
589589 self.failUnlessRaises(dns.name.BadLabelType, bad)
590590
591 def testParent1(self):
592 n = dns.name.from_text('foo.bar.')
593 self.failUnless(n.parent() == dns.name.from_text('bar.'))
594 self.failUnless(n.parent().parent() == dns.name.root)
595
596 def testParent2(self):
597 n = dns.name.from_text('foo.bar', None)
598 self.failUnless(n.parent() == dns.name.from_text('bar', None))
599 self.failUnless(n.parent().parent() == dns.name.empty)
600
601 def testParent3(self):
602 def bad():
603 n = dns.name.root
604 n.parent()
605 self.failUnlessRaises(dns.name.NoParent, bad)
606
607 def testParent4(self):
608 def bad():
609 n = dns.name.empty
610 n.parent()
611 self.failUnlessRaises(dns.name.NoParent, bad)
612
591613 if __name__ == '__main__':
592614 unittest.main()
7676 self.failUnless(cache.get((name, dns.rdatatype.A, dns.rdataclass.IN))
7777 is None)
7878
79 def testZoneForName1(self):
80 name = dns.name.from_text('www.dnspython.org.')
81 ezname = dns.name.from_text('dnspython.org.')
82 zname = dns.resolver.zone_for_name(name)
83 self.failUnless(zname == ezname)
84
85 def testZoneForName2(self):
86 name = dns.name.from_text('a.b.www.dnspython.org.')
87 ezname = dns.name.from_text('dnspython.org.')
88 zname = dns.resolver.zone_for_name(name)
89 self.failUnless(zname == ezname)
90
91 def testZoneForName3(self):
92 name = dns.name.from_text('dnspython.org.')
93 ezname = dns.name.from_text('dnspython.org.')
94 zname = dns.resolver.zone_for_name(name)
95 self.failUnless(zname == ezname)
96
97 def testZoneForName4(self):
98 def bad():
99 name = dns.name.from_text('dnspython.org', None)
100 zname = dns.resolver.zone_for_name(name)
101 self.failUnlessRaises(dns.resolver.NotAbsolute, bad)
102
79103 if __name__ == '__main__':
80104 unittest.main()
290290 self.failUnless(ns == [dns.name.from_text('ns1', None),
291291 dns.name.from_text('ns2', None)])
292292
293 def testIterateAllRdatasets(self):
294 z = dns.zone.from_text(example_text, 'example.', relativize=True)
295 ns = [n for n, r in z.iterate_rdatasets()]
296 ns.sort()
297 self.failUnless(ns == [dns.name.from_text('@', None),
298 dns.name.from_text('@', None),
299 dns.name.from_text('bar.foo', None),
300 dns.name.from_text('ns1', None),
301 dns.name.from_text('ns2', None)])
302
293303 def testIterateRdatas(self):
294304 z = dns.zone.from_text(example_text, 'example.', relativize=True)
295305 l = list(z.iterate_rdatas('A'))
296306 l.sort()
297307 exl = [(dns.name.from_text('ns1', None),
308 3600,
309 dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
310 '10.0.0.1')),
311 (dns.name.from_text('ns2', None),
312 3600,
313 dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
314 '10.0.0.2'))]
315 self.failUnless(l == exl)
316
317 def testIterateAllRdatas(self):
318 z = dns.zone.from_text(example_text, 'example.', relativize=True)
319 l = list(z.iterate_rdatas())
320 l.sort()
321 exl = [(dns.name.from_text('@', None),
322 3600,
323 dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS,
324 'ns1')),
325 (dns.name.from_text('@', None),
326 3600,
327 dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS,
328 'ns2')),
329 (dns.name.from_text('@', None),
330 3600,
331 dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.SOA,
332 'foo bar 1 2 3 4 5')),
333 (dns.name.from_text('bar.foo', None),
334 300,
335 dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.MX,
336 '0 blaz.foo')),
337 (dns.name.from_text('ns1', None),
298338 3600,
299339 dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
300340 '10.0.0.1')),