import re from fqdn._compat import cached_property class FQDN: """ From https://tools.ietf.org/html/rfc1035#page-9, RFC 1035 3.1. Name space definitions: Domain names in messages are expressed in terms of a sequence of labels. Each label is represented as a one octet length field followed by that number of octets. Since every domain name ends with the null label of the root, a domain name is terminated by a length byte of zero. The high order two bits of every length octet must be zero, and the remaining six bits of the length field limit the label to 63 octets or less. To simplify implementations, the total length of a domain name (i.e., label octets and label length octets) is restricted to 255 octets or less. Therefore the max length of a domain name is actually 253 ASCII bytes without the trailing null byte or the leading length byte, and the max length of a label is 63 bytes without the leading length byte. """ PREFERRED_NAME_SYNTAX_REGEXSTR = ( r"^((?![-])[-A-Z\d]{1,63}(? 253: return False regex_pass = self._regex.match(self._fqdn) if not regex_pass: return False return self.labels_count >= self._min_labels @property def labels_count(self): has_terminal_dot = self._fqdn[-1] == "." count = self._fqdn.count(".") + (0 if has_terminal_dot else 1) return count @cached_property def is_valid_absolute(self): """ True for a fully-qualified domain name (FQDN) that is RFC preferred-form compliant and ends with a `.`. With relative FQDNS in DNS lookups, the current hosts domain name or search domains may be appended. """ return self._fqdn.endswith(".") and self.is_valid @cached_property def is_valid_relative(self): """ True for a validated fully-qualified domain name that compiles with the RFC preferred-form and does not ends with a `.`. """ return not self._fqdn.endswith(".") and self.is_valid @cached_property def absolute(self): """ The FQDN as a string in absolute form """ if not self.is_valid: raise ValueError("invalid FQDN `{0}`".format(self._fqdn)) if self.is_valid_absolute: return self._fqdn return "{0}.".format(self._fqdn) @cached_property def relative(self): """ The FQDN as a string in relative form """ if not self.is_valid: raise ValueError("invalid FQDN `{0}`".format(self._fqdn)) if self.is_valid_absolute: return self._fqdn[:-1] return self._fqdn def __eq__(self, other): if isinstance(other, FQDN): return self.absolute == other.absolute def __hash__(self): return hash(self.absolute) + hash("fqdn")