Source code for encommon.parse.network

"""
Functions and routines associated with Enasis Network Common Library.

This file is part of Enasis Network software eco-system. Distribution
is permitted, for more information consult the project license file.
"""



from contextlib import suppress
from typing import Any
from typing import Optional

from netaddr import IPAddress
from netaddr import IPNetwork



[docs] class Network: """ Convert the network into the various supported formats. :param source: Network IPv4 or IPv6 network or address. """ __source: IPNetwork def __init__( self, source: str, ) -> None: """ Initialize instance for class using provided parameters. """ network = IPNetwork(source) self.__source = network def __repr__( self, ) -> str: """ Built-in method for representing the values for instance. :returns: String representation for values from instance. """ return f"Network('{self.address_cidr}')" def __hash__( self, ) -> int: """ Built-in method used when performing hashing operations. :returns: Integer hash value for the internal reference. """ return hash(self.__source) def __str__( self, ) -> str: """ Built-in method for representing the values for instance. :returns: String representation for values from instance. """ return self.address_cidr def __eq__( self, other: object, ) -> bool: """ Built-in method for comparing this instance with another. :param other: Other value being compared with instance. :returns: Boolean indicating outcome from the operation. """ source = self.__source with suppress(Exception): other = IPNetwork(str(other)) return source == other return False def __ne__( self, other: object, ) -> bool: """ Built-in method for comparing this instance with another. :param other: Other value being compared with instance. :returns: Boolean indicating outcome from the operation. """ return not self.__eq__(other) @property def source( self, ) -> IPNetwork: """ Return the value for the attribute from class instance. :returns: Value for the attribute from class instance. """ return self.__source @property def version( self, ) -> int: """ Return the value for the attribute from class instance. :returns: Value for the attribute from class instance. """ return self.__source.version @property def cidr( self, ) -> int: """ Return the value for the attribute from class instance. :returns: Value for the attribute from class instance. """ source = self.__source return source.prefixlen @property def address( self, ) -> str: """ Return the value for the attribute from class instance. :returns: Value for the attribute from class instance. """ source = self.__source return str(source.ip) @property def address_cidr( self, ) -> str: """ Return the value for the attribute from class instance. :returns: Value for the attribute from class instance. """ address = self.address return f'{address}/{self.cidr}' @property def address_host( self, ) -> str: """ Return the value for the attribute from class instance. :returns: Value for the attribute from class instance. """ address = self.address prefix = ( 128 if self.version == 6 else 32) return f'{address}/{prefix}' @property def network( self, ) -> str: """ Return the value for the attribute from class instance. :returns: Value for the attribute from class instance. """ source = self.__source return str(source.network) @property def network_cidr( self, ) -> str: """ Return the value for the attribute from class instance. :returns: Value for the attribute from class instance. """ network = self.network return f'{network}/{self.cidr}' @property def broadcast( self, ) -> Optional[str]: """ Return the value for the attribute from class instance. :returns: Value for the attribute from class instance. """ source = self.__source address = source.broadcast if address is None: return None return str(address) @property def padded( self, ) -> str: """ Return the value for the attribute from class instance. :returns: Value for the attribute from class instance. """ if self.version != 4: raise ValueError('version') address = self.address octets = address.split('.') pads = [ x.zfill(3) for x in octets] return '.'.join(pads) @property def reverse( self, ) -> str: """ Return the value for the attribute from class instance. :returns: Value for the attribute from class instance. """ if self.version != 4: raise ValueError('version') address = self.address octets = address.split('.') reverse = list(reversed(octets)) return '.'.join(reverse) @property def hwaddr( self, ) -> str: """ Return the value for the attribute from class instance. :returns: Value for the attribute from class instance. """ if self.version != 4: raise ValueError('version') padded = self.padded nodots = ( padded .replace('.', '')) ranged = range( 0, len(nodots), 2) pairs = [ nodots[x:x + 2] for x in ranged] return '-'.join(pairs) @property def netmask( self, ) -> str: """ Return the value for the attribute from class instance. :returns: Value for the attribute from class instance. """ source = self.__source return str(source.netmask) @property def ispublic( self, ) -> bool: """ Return the boolean indicating whether instance is state. """ return ( self.source.ip .is_global()) @property def isprivate( self, ) -> bool: """ Return the boolean indicating whether instance is state. """ return not self.ispublic @property def islinklocal( self, ) -> bool: """ Return the boolean indicating whether instance is state. """ return ( self.source .is_link_local()) @property def islocalhost( self, ) -> bool: """ Return the boolean indicating whether instance is state. """ return ( self.source .is_loopback())
[docs] def insubnet_ip( address: str, networks: str | list[str] | tuple[str, ...], ) -> bool: """ Return the boolean indicating address is in the network. :param address: Provided address to find in the network. :param network: Networks which values can be within any. :returns: Boolean indicating address is in the network. """ if isinstance(networks, str): networks = [networks] networks = list(networks) if not isvalid_ip(address): raise ValueError('address') naddr = Network(address) if (naddr.version == 4 and naddr.cidr == 32): address = naddr.address if (naddr.version == 6 and naddr.cidr == 128): address = naddr.address parsed = IPAddress(address) return any( parsed in IPNetwork(x) for x in networks)
[docs] def isvalid_ip( value: Any, # noqa: ANN401 ) -> bool: """ Return the boolean indicating whether the value is valid. :param value: Value that will be validated as an address. :returns: Boolean indicating whether the value is valid. """ value = str(value) try: Network(value) return True except Exception: return False