The dns.zone.Zone Class

The Zone class provides a non-thread-safe implementation of a DNS zone, as well as a lightweight transation mechanism that allows it to be atomically updated. For more complicated transactional needs, or for concurrency, please use the dns.versioned.Zone class (described below).

class dns.zone.Zone(origin, rdclass=<RdataClass.IN: 1>, relativize=True)[source]

A DNS zone.

A Zone is a mapping from names to nodes. The zone object may be treated like a Python dictionary, e.g. zone[name] will retrieve the node associated with that name. The name may be a dns.name.Name object, or it may be a string. In either case, if the name is relative it is treated as relative to the origin of the zone.

Initialize a zone object.

origin is the origin of the zone. It may be a dns.name.Name, a str, or None. If None, then the zone’s origin will be set by the first $ORIGIN line in a zone file.

rdclass, an int, the zone’s rdata class; the default is class IN.

relativize, a bool, determine’s whether domain names are relativized to the zone’s origin. The default is True.

rdclass

The zone’s rdata class, an int; the default is class IN.

origin

The origin of the zone, a dns.name.Name.

nodes

A dictionary mapping the names of nodes in the zone to the nodes themselves.

relativize

A bool, which is True if names in the zone should be relativized.

check_origin()[source]

Do some simple checking of the zone’s origin.

Raises dns.zone.NoSOA if there is no SOA RRset.

Raises dns.zone.NoNS if there is no NS RRset.

Raises KeyError if there is no origin node.

delete_node(name)[source]

Delete the specified node if it exists.

name: the name of the node to find. The value may be a dns.name.Name or a str. If absolute, the name must be a subdomain of the zone’s origin. If zone.relativize is True, then the name will be relativized.

It is not an error if the node does not exist.

delete_rdataset(name, rdtype, covers=<RdataType.TYPE0: 0>)[source]

Delete the rdataset matching rdtype and covers, if it exists at the node specified by name.

It is not an error if the node does not exist, or if there is no matching rdataset at the node.

If the node has no rdatasets after the deletion, it will itself be deleted.

name: the name of the node to find. The value may be a dns.name.Name or a str. If absolute, the name must be a subdomain of the zone’s origin. If zone.relativize is True, then the name will be relativized.

rdtype, an int or str, the rdata type desired.

covers, an int or str or None, the covered type. Usually this value is dns.rdatatype.NONE, but if the rdtype is dns.rdatatype.SIG or dns.rdatatype.RRSIG, then the covers value will be the rdata type the SIG/RRSIG covers. The library treats the SIG and RRSIG types as if they were a family of types, e.g. RRSIG(A), RRSIG(NS), RRSIG(SOA). This makes RRSIGs much easier to work with than if RRSIGs covering different rdata types were aggregated into a single RRSIG rdataset.

find_node(name, create=False)[source]

Find a node in the zone, possibly creating it.

name: the name of the node to find. The value may be a dns.name.Name or a str. If absolute, the name must be a subdomain of the zone’s origin. If zone.relativize is True, then the name will be relativized.

create, a bool. If true, the node will be created if it does not exist.

Raises KeyError if the name is not known and create was not specified, or if the name was not a subdomain of the origin.

Returns a dns.node.Node.

find_rdataset(name, rdtype, covers=<RdataType.TYPE0: 0>, create=False)[source]

Look for an rdataset with the specified name and type in the zone, and return an rdataset encapsulating it.

The rdataset returned is not a copy; changes to it will change the zone.

KeyError is raised if the name or type are not found.

name: the name of the node to find. The value may be a dns.name.Name or a str. If absolute, the name must be a subdomain of the zone’s origin. If zone.relativize is True, then the name will be relativized.

rdtype, an int or str, the rdata type desired.

covers, an int or str or None, the covered type. Usually this value is dns.rdatatype.NONE, but if the rdtype is dns.rdatatype.SIG or dns.rdatatype.RRSIG, then the covers value will be the rdata type the SIG/RRSIG covers. The library treats the SIG and RRSIG types as if they were a family of types, e.g. RRSIG(A), RRSIG(NS), RRSIG(SOA). This makes RRSIGs much easier to work with than if RRSIGs covering different rdata types were aggregated into a single RRSIG rdataset.

create, a bool. If true, the node will be created if it does not exist.

Raises KeyError if the name is not known and create was not specified, or if the name was not a subdomain of the origin.

Returns a dns.rdataset.Rdataset.

find_rrset(name, rdtype, covers=<RdataType.TYPE0: 0>)[source]

Look for an rdataset with the specified name and type in the zone, and return an RRset encapsulating it.

This method is less efficient than the similar find_rdataset() because it creates an RRset instead of returning the matching rdataset. It may be more convenient for some uses since it returns an object which binds the owner name to the rdataset.

This method may not be used to create new nodes or rdatasets; use find_rdataset instead.

name: the name of the node to find. The value may be a dns.name.Name or a str. If absolute, the name must be a subdomain of the zone’s origin. If zone.relativize is True, then the name will be relativized.

rdtype, an int or str, the rdata type desired.

covers, an int or str or None, the covered type. Usually this value is dns.rdatatype.NONE, but if the rdtype is dns.rdatatype.SIG or dns.rdatatype.RRSIG, then the covers value will be the rdata type the SIG/RRSIG covers. The library treats the SIG and RRSIG types as if they were a family of types, e.g. RRSIG(A), RRSIG(NS), RRSIG(SOA). This makes RRSIGs much easier to work with than if RRSIGs covering different rdata types were aggregated into a single RRSIG rdataset.

create, a bool. If true, the node will be created if it does not exist.

Raises KeyError if the name is not known and create was not specified, or if the name was not a subdomain of the origin.

Returns a dns.rrset.RRset or None.

get_class()[source]

The class of the transaction manager.

get_node(name, create=False)[source]

Get a node in the zone, possibly creating it.

This method is like find_node(), except it returns None instead of raising an exception if the node does not exist and creation has not been requested.

name: the name of the node to find. The value may be a dns.name.Name or a str. If absolute, the name must be a subdomain of the zone’s origin. If zone.relativize is True, then the name will be relativized.

create, a bool. If true, the node will be created if it does not exist.

Raises KeyError if the name is not known and create was not specified, or if the name was not a subdomain of the origin.

Returns a dns.node.Node or None.

get_rdataset(name, rdtype, covers=<RdataType.TYPE0: 0>, create=False)[source]

Look for an rdataset with the specified name and type in the zone.

This method is like find_rdataset(), except it returns None instead of raising an exception if the rdataset does not exist and creation has not been requested.

The rdataset returned is not a copy; changes to it will change the zone.

name: the name of the node to find. The value may be a dns.name.Name or a str. If absolute, the name must be a subdomain of the zone’s origin. If zone.relativize is True, then the name will be relativized.

rdtype, an int or str, the rdata type desired.

covers, an int or str or None, the covered type. Usually this value is dns.rdatatype.NONE, but if the rdtype is dns.rdatatype.SIG or dns.rdatatype.RRSIG, then the covers value will be the rdata type the SIG/RRSIG covers. The library treats the SIG and RRSIG types as if they were a family of types, e.g. RRSIG(A), RRSIG(NS), RRSIG(SOA). This makes RRSIGs much easier to work with than if RRSIGs covering different rdata types were aggregated into a single RRSIG rdataset.

create, a bool. If true, the node will be created if it does not exist.

Raises KeyError if the name is not known and create was not specified, or if the name was not a subdomain of the origin.

Returns a dns.rdataset.Rdataset or None.

get_rrset(name, rdtype, covers=<RdataType.TYPE0: 0>)[source]

Look for an rdataset with the specified name and type in the zone, and return an RRset encapsulating it.

This method is less efficient than the similar get_rdataset() because it creates an RRset instead of returning the matching rdataset. It may be more convenient for some uses since it returns an object which binds the owner name to the rdataset.

This method may not be used to create new nodes or rdatasets; use get_rdataset() instead.

name: the name of the node to find. The value may be a dns.name.Name or a str. If absolute, the name must be a subdomain of the zone’s origin. If zone.relativize is True, then the name will be relativized.

rdtype, an int or str, the rdata type desired.

covers, an int or str or None, the covered type. Usually this value is dns.rdatatype.NONE, but if the rdtype is dns.rdatatype.SIG or dns.rdatatype.RRSIG, then the covers value will be the rdata type the SIG/RRSIG covers. The library treats the SIG and RRSIG types as if they were a family of types, e.g. RRSIG(A), RRSIG(NS), RRSIG(SOA). This makes RRSIGs much easier to work with than if RRSIGs covering different rdata types were aggregated into a single RRSIG rdataset.

create, a bool. If true, the node will be created if it does not exist.

Raises KeyError if the name is not known and create was not specified, or if the name was not a subdomain of the origin.

Returns a dns.rrset.RRset or None.

iterate_rdatas(rdtype=<RdataType.ANY: 255>, covers=<RdataType.TYPE0: 0>)[source]

Return a generator which yields (name, ttl, rdata) tuples for all rdatas in the zone which have the specified rdtype and covers. If rdtype is dns.rdatatype.ANY, the default, then all rdatas will be matched.

rdtype, an int or str, the rdata type desired.

covers, an int or str or None, the covered type. Usually this value is dns.rdatatype.NONE, but if the rdtype is dns.rdatatype.SIG or dns.rdatatype.RRSIG, then the covers value will be the rdata type the SIG/RRSIG covers. The library treats the SIG and RRSIG types as if they were a family of types, e.g. RRSIG(A), RRSIG(NS), RRSIG(SOA). This makes RRSIGs much easier to work with than if RRSIGs covering different rdata types were aggregated into a single RRSIG rdataset.

iterate_rdatasets(rdtype=<RdataType.ANY: 255>, covers=<RdataType.TYPE0: 0>)[source]

Return a generator which yields (name, rdataset) tuples for all rdatasets in the zone which have the specified rdtype and covers. If rdtype is dns.rdatatype.ANY, the default, then all rdatasets will be matched.

rdtype, an int or str, the rdata type desired.

covers, an int or str or None, the covered type. Usually this value is dns.rdatatype.NONE, but if the rdtype is dns.rdatatype.SIG or dns.rdatatype.RRSIG, then the covers value will be the rdata type the SIG/RRSIG covers. The library treats the SIG and RRSIG types as if they were a family of types, e.g. RRSIG(A), RRSIG(NS), RRSIG(SOA). This makes RRSIGs much easier to work with than if RRSIGs covering different rdata types were aggregated into a single RRSIG rdataset.

node_factory

alias of dns.node.Node

origin_information()[source]

Returns a tuple

(absolute_origin, relativize, effective_origin)

giving the absolute name of the default origin for any relative domain names, the “effective origin”, and whether names should be relativized. The “effective origin” is the absolute origin if relativize is False, and the empty name if relativize is true. (The effective origin is provided even though it can be computed from the absolute_origin and relativize setting because it avoids a lot of code duplication.)

If the returned names are None, then no origin information is available.

This information is used by code working with transactions to allow it to coordinate relativization. The transaction code itself takes what it gets (i.e. does not change name relativity).

reader()[source]

Begin a read-only transaction.

replace_rdataset(name, replacement)[source]

Replace an rdataset at name.

It is not an error if there is no rdataset matching I{replacement}.

Ownership of the replacement object is transferred to the zone; in other words, this method does not store a copy of replacement at the node, it stores replacement itself.

If the node does not exist, it is created.

name: the name of the node to find. The value may be a dns.name.Name or a str. If absolute, the name must be a subdomain of the zone’s origin. If zone.relativize is True, then the name will be relativized.

replacement, a dns.rdataset.Rdataset, the replacement rdataset.

to_file(f, sorted=True, relativize=True, nl=None, want_comments=False)[source]

Write a zone to a file.

f, a file or str. If f is a string, it is treated as the name of a file to open.

sorted, a bool. If True, the default, then the file will be written with the names sorted in DNSSEC order from least to greatest. Otherwise the names will be written in whatever order they happen to have in the zone’s dictionary.

relativize, a bool. If True, the default, then domain names in the output will be relativized to the zone’s origin if possible.

nl, a str or None. The end of line string. If not None, the output will use the platform’s native end-of-line marker (i.e. LF on POSIX, CRLF on Windows).

want_comments, a bool. If True, emit end-of-line comments as part of writing the file. If False, the default, do not emit them.

to_text(sorted=True, relativize=True, nl=None, want_comments=False)[source]

Return a zone’s text as though it were written to a file.

sorted, a bool. If True, the default, then the file will be written with the names sorted in DNSSEC order from least to greatest. Otherwise the names will be written in whatever order they happen to have in the zone’s dictionary.

relativize, a bool. If True, the default, then domain names in the output will be relativized to the zone’s origin if possible.

nl, a str or None. The end of line string. If not None, the output will use the platform’s native end-of-line marker (i.e. LF on POSIX, CRLF on Windows).

want_comments, a bool. If True, emit end-of-line comments as part of writing the file. If False, the default, do not emit them.

Returns a str.

writer(replacement=False)[source]

Begin a writable transaction.

replacement, a bool. If True, the content of the transaction completely replaces any prior content. If False, the default, then the content of the transaction updates the existing content.

A Zone has a class attribute node_factory which is used to create new nodes and defaults to dns.node.Node. Zone may be subclassed if a different node factory is desired. The node factory is a class or callable that returns a subclass of dns.node.Node.

The dns.versioned.Zone Class

A versioned Zone is a subclass of Zone that provides a thread-safe multiversioned transactional API. There can be many concurrent readers, of possibly different versions, and at most one active writer. Others cannot see the changes being made by the writer until it commits. Versions are immutable once committed.

The read-only parts of the standard zone API continue to be available, and are equivalent to doing a single-query read-only transaction. Note that unless reading is done through a transaction, version stability is not guaranteed between successive calls. Attempts to use zone API methods that directly manipulate the zone, e.g. replace_rdataset will result in a UseTransaction exception.

Transactions are context managers, and are created with reader() or writer(). For example:

# Print the SOA serial number of the most recent version
with zone.reader() as txn:
    rdataset = txn.get('@', 'in', 'soa')
    print('The most recent serial number is', rdataset[0].serial)

# Write an A RR and increment the SOA serial number to the next value.
with zone.writer() as txn:
    txn.replace('node1', dns.rdataset.from_text('in', 'a', 300,
                '10.0.0.1'))
    txn.set_serial()

See below for more information on the Transaction API.

class dns.versioned.Zone(origin, rdclass=<RdataClass.IN: 1>, relativize=True, pruning_policy=None)[source]

Initialize a versioned zone object.

origin is the origin of the zone. It may be a dns.name.Name, a str, or None. If None, then the zone’s origin will be set by the first $ORIGIN line in a zone file.

rdclass, an int, the zone’s rdata class; the default is class IN.

relativize, a bool, determine’s whether domain names are relativized to the zone’s origin. The default is True.

pruning policy, a function taking a Version and returning a bool, or None. Should the version be pruned? If None, the default policy, which retains one version is used.

rdclass

The zone’s rdata class, an int; the default is class IN.

origin

The origin of the zone, a dns.name.Name.

nodes

A dictionary mapping the names of nodes in the zone to the nodes themselves.

relativize

A bool, which is True if names in the zone should be relativized.

find_node(name, create=False)[source]

Find a node in the zone, possibly creating it.

name: the name of the node to find. The value may be a dns.name.Name or a str. If absolute, the name must be a subdomain of the zone’s origin. If zone.relativize is True, then the name will be relativized.

create, a bool. If true, the node will be created if it does not exist.

Raises KeyError if the name is not known and create was not specified, or if the name was not a subdomain of the origin.

Returns a dns.node.Node.

find_rdataset(name, rdtype, covers=<RdataType.TYPE0: 0>, create=False)[source]

Look for an rdataset with the specified name and type in the zone, and return an rdataset encapsulating it.

The rdataset returned is not a copy; changes to it will change the zone.

KeyError is raised if the name or type are not found.

name: the name of the node to find. The value may be a dns.name.Name or a str. If absolute, the name must be a subdomain of the zone’s origin. If zone.relativize is True, then the name will be relativized.

rdtype, an int or str, the rdata type desired.

covers, an int or str or None, the covered type. Usually this value is dns.rdatatype.NONE, but if the rdtype is dns.rdatatype.SIG or dns.rdatatype.RRSIG, then the covers value will be the rdata type the SIG/RRSIG covers. The library treats the SIG and RRSIG types as if they were a family of types, e.g. RRSIG(A), RRSIG(NS), RRSIG(SOA). This makes RRSIGs much easier to work with than if RRSIGs covering different rdata types were aggregated into a single RRSIG rdataset.

create, a bool. If true, the node will be created if it does not exist.

Raises KeyError if the name is not known and create was not specified, or if the name was not a subdomain of the origin.

Returns a dns.rdataset.Rdataset.

get_rdataset(name, rdtype, covers=<RdataType.TYPE0: 0>, create=False)[source]

Look for an rdataset with the specified name and type in the zone.

This method is like find_rdataset(), except it returns None instead of raising an exception if the rdataset does not exist and creation has not been requested.

The rdataset returned is not a copy; changes to it will change the zone.

name: the name of the node to find. The value may be a dns.name.Name or a str. If absolute, the name must be a subdomain of the zone’s origin. If zone.relativize is True, then the name will be relativized.

rdtype, an int or str, the rdata type desired.

covers, an int or str or None, the covered type. Usually this value is dns.rdatatype.NONE, but if the rdtype is dns.rdatatype.SIG or dns.rdatatype.RRSIG, then the covers value will be the rdata type the SIG/RRSIG covers. The library treats the SIG and RRSIG types as if they were a family of types, e.g. RRSIG(A), RRSIG(NS), RRSIG(SOA). This makes RRSIGs much easier to work with than if RRSIGs covering different rdata types were aggregated into a single RRSIG rdataset.

create, a bool. If true, the node will be created if it does not exist.

Raises KeyError if the name is not known and create was not specified, or if the name was not a subdomain of the origin.

Returns a dns.rdataset.Rdataset or None.

node_factory

alias of Node

reader(id=None, serial=None)[source]

Begin a read-only transaction.

set_max_versions(max_versions)[source]

Set a pruning policy that retains up to the specified number of versions

set_pruning_policy(policy)[source]

Set the pruning policy for the zone.

The policy function takes a Version and returns True if the version should be pruned, and False otherwise. None may also be specified for policy, in which case the default policy is used.

Pruning checking proceeds from the least version and the first time the function returns False, the checking stops. I.e. the retained versions are always a consecutive sequence.

writer(replacement=False)[source]

Begin a writable transaction.

replacement, a bool. If True, the content of the transaction completely replaces any prior content. If False, the default, then the content of the transaction updates the existing content.

The TransactionManager Class

This is the abstract base class of all objects that support transactions.

class dns.transaction.TransactionManager[source]
from_wire_origin()[source]

Origin to use in from_wire() calls.

get_class()[source]

The class of the transaction manager.

origin_information()[source]

Returns a tuple

(absolute_origin, relativize, effective_origin)

giving the absolute name of the default origin for any relative domain names, the “effective origin”, and whether names should be relativized. The “effective origin” is the absolute origin if relativize is False, and the empty name if relativize is true. (The effective origin is provided even though it can be computed from the absolute_origin and relativize setting because it avoids a lot of code duplication.)

If the returned names are None, then no origin information is available.

This information is used by code working with transactions to allow it to coordinate relativization. The transaction code itself takes what it gets (i.e. does not change name relativity).

reader()[source]

Begin a read-only transaction.

writer(replacement=False)[source]

Begin a writable transaction.

replacement, a bool. If True, the content of the transaction completely replaces any prior content. If False, the default, then the content of the transaction updates the existing content.

The Transaction Class

class dns.transaction.Transaction(manager, replacement=False, read_only=False)[source]
add(*args)[source]

Add records.

The arguments may be:

  • rrset
  • name, rdataset…
  • name, ttl, rdata…
changed()[source]

Has this transaction changed anything?

For read-only transactions, the result is always False.

For writable transactions, the result is True if at some time during the life of the transaction, the content was changed.

commit()[source]

Commit the transaction.

Normally transactions are used as context managers and commit or rollback automatically, but it may be done explicitly if needed. A dns.transaction.Ended exception will be raised if you try to use a transaction after it has been committed or rolled back.

Raises an exception if the commit fails (in which case the transaction is also rolled back.

delete(*args)[source]

Delete records.

It is not an error if some of the records are not in the existing set.

The arguments may be:

  • rrset
  • name
  • name, rdataclass, rdatatype, [covers]
  • name, rdataset…
  • name, rdata…
delete_exact(*args)[source]

Delete records.

The arguments may be:

  • rrset
  • name
  • name, rdataclass, rdatatype, [covers]
  • name, rdataset…
  • name, rdata…

Raises dns.transaction.DeleteNotExact if some of the records are not in the existing set.

get(name, rdtype, covers=<RdataType.TYPE0: 0>)[source]

Return the rdataset associated with name, rdtype, and covers, or None if not found.

Note that the returned rdataset is immutable.

name_exists(name)[source]

Does the specified name exist?

replace(*args)[source]

Replace the existing rdataset at the name with the specified rdataset, or add the specified rdataset if there was no existing rdataset.

The arguments may be:

  • rrset
  • name, rdataset…
  • name, ttl, rdata…

Note that if you want to replace the entire node, you should do a delete of the name followed by one or more calls to add() or replace().

rollback()[source]

Rollback the transaction.

Normally transactions are used as context managers and commit or rollback automatically, but it may be done explicitly if needed. A dns.transaction.AlreadyEnded exception will be raised if you try to use a transaction after it has been committed or rolled back.

Rollback cannot otherwise fail.

update_serial(value=1, relative=True, name=<DNS name @>)[source]

Update the serial number.

value, an int, is an increment if relative is True, or the actual value to set if relative is False.

Raises KeyError if there is no SOA rdataset at name.

Raises ValueError if value is negative or if the increment is so large that it would cause the new serial to be less than the prior value.