Using hostname

Common signature

The class, Hostname, and the function, is_hostname(), described here have a common signature:

funcOrClass(candidate: Any, **kwargs: bool) -> rtype

In normal usage, candidate must be a str, and non-string inputs will result in failure, though not a TypeError. [1]

Details on the keyword arguments are described in Flags below.

The function

hostname.is_hostname(candidate, **kwargs) TypeGuard[Hostname]

retruns True iff candidate is a standards complient Internet hostname.

Return type:

bool

**kwargs can be any of
  • allow_idna (default True),

  • allow_underscore (default False),

  • allow_empty (default False)

The function, hostname.is_hostname() returns True if and only if its argument is a syntactically valid hostname. It’s behavior can be adjusted slightly with some flags which can be set as keyword arguements.

>>> is_hostname("a.go-od.example")
True
>>> is_hostname("a.-bad.example")
False

Additionally it acts as a PEP 647 typing.TypeGuard, allowing type checkers to know that any object which passes the test is a hostname.Hostname.

import hostname

def do_something_with_hostname(hostname: hostname.Hostname) -> None:
    ...

name1: str = "www.example"

do_something_with_hostname(name1)  # Fails type checking

if not hostname.is_hostname(name1):
    raise TypeError('Expected valid Hostname')
do_something_with_hostname(name1)  # Passes type checking

name1 = name1.upper() # creates new str object.
do_something_with_hostname(name1)  # Fails type checking

Note that the typing.TypeGuard mechanism only affects static type checking. To create an instance of the hostname.Hostname class initilize a Hostname:

>>> s = 'example.com'
>>> is_hostname(s)
True
>>> isinstance(s, hostname.Hostname)
False
>>> t = hostname.Hostname('example.com')
>>> isinstance(t, hostname.Hostname)
True

Note

Although underlyingly hostnames are case insensitive that does not hold for internationalized hostnames. Althouh both valid, straße.example is not equivalent to STRASSE.EXAMPLE.

>>> 'straße.example'.upper()
'STRASSE.EXAMPLE'

Hostname class

The hostname.Hostname is a subtype of str.

If candidate is not a valid hostname, initializing the class will raise one of the hostname.exception.HostnameException Exceptions. **kwargs are described in Flags.

class hostname.Hostname(candidate, **kwargs)

A string that is also a valid hostname.

property dnsname: Name

Returns a dns.name.Name.

property flags: dict[str, bool]

Returns the flags used when validating this hostname

property labels: list[bytes]

Returns a list of labels, ordered from leftmost to rightmost.

Returned list never includes the DNS root label "". If you want the full DNS labels use dnsname() and use the dns.name.Name.labels for that list.

Because Hostname is a subclass of str, all str methods are available. But it is important to note that what is returned by those inherited methods is not a hostname.Hostname.

>>> h = hostname.Hostname('foo.example')
>>> isinstance(h, hostname.Hostname)
True
>>> isinstance(h.upper(), hostname.Hostname)
False

Flags

The possible keyword arguments are the booleans, allow_idna, allow_underscore, and allow_empty.

allow_idna (Allow non-ASCII hostnames)

When True, a hostname candidate hostname like "szárba.szökik.hu" will be accepted. When False such a candidate will raise an hostname.exception.NotASCIIError error.

Default True

>>> is_hostname("szárba.szökik.hu")
True
>>> is_hostname("szárba.szökik.hu", allow_idna=False)
False
>>> is_hostname("szarba.szokik.hu", allow_idna=False)
True
allow_empty (Allow the empty string as a valid hostname)

When True, a hostname candidate hostname like "" will be accepted. When False such a candidate will raise an hostname.exception.NoLabelError error.

Default False

>>> is_hostname("")
False
>>> is_hostname("", allow_empty=True)
True
allow_underscore (Allow underscore in leftmost label)

When True, a hostname candidate hostname like "under_score.in.host" will be accepted. When False such a candidate will raise an hostname.exception.UnderscoreError error.

Default False

>>> is_hostname("under_score.in.host")
False
>>> is_hostname("under_score.in.host", allow_underscore=True)
True

In all cases, a candidate with an underscore anywhere other than in the first (leftmost) label, such as "underscore.in.net_work" will raise an hostname.exception.UnderscoreError.

>>> is_hostname("leftmost.not_leftmost.example")
False
>>> is_hostname("leftmost.not_leftmost.example", allow_underscore=True)
False

See Underscores for details and rationale.

Footnotes