# -*- coding: utf-8 -*- from collections.abc import Container import ipaddress import itertools class InternalIPS(Container): """ InternalIPS allows to specify CIDRs for INTERNAL_IPS. It takes an iterable of ip addresses or ranges. Inspiration taken from netaddr.IPSet, please use it if you can since it support more advanced features like optimizing ranges and lookups. """ __slots__ = ["_cidrs"] def __init__(self, iterable, sort_by_size=False): """ Constructor. :param iterable: (optional) an iterable containing IP addresses and subnets. :param sort_by_size: sorts internal list according to size of ip ranges, largest first. """ self._cidrs = [] for address in iterable: self._cidrs.append(ipaddress.ip_network(address)) if sort_by_size: self._cidrs = sorted(self._cidrs) def __contains__(self, address): """ :param ip: An IP address or subnet. :return: ``True`` if IP address or subnet is a member of this InternalIPS set. """ address = ipaddress.ip_address(address) for cidr in self._cidrs: if address in cidr: return True return False def __hash__(self): """ Raises ``TypeError`` if this method is called. """ raise TypeError('InternalIPS containers are unhashable!') def __len__(self): """ :return: the cardinality of this InternalIPS set. """ return sum(cidr.num_addresses for cidr in self._cidrs) def __iter__(self): """ :return: an iterator over the IP addresses within this IP set. """ return itertools.chain(*self._cidrs) def iter_cidrs(self): """ :return: an iterator over individual IP subnets within this IP set. """ return sorted(self._cidrs)