U .Ѫ_g@sddZddlZddlmZmZmZmZmZm Z ddl m Z m Z m Z ddZddZGd d d eZdS) z2Set based operations for IP addresses and subnets.N) IPNetwork IPAddressIPRange cidr_merge cidr_excludeiprange_to_cidrs) _sys_maxint _dict_keys _int_typec Cs|jj}||}|j|jkr4|||j|jdf|d7}|}|t|kr||}||kr^q|jd|jkrpn|||jd|jdf|d7}|}q@|jd}|j} || kr|||| f|S)aCalculate IPSet([supernet]) - IPSet(subnets). Assumptions: subnets is sorted, subnet_idx points to the first element in subnets that is a subnet of supernet. Results are appended to the ranges parameter as tuples of in format (version, first, last). Return value is the first subnet_idx that does not point to a subnet of supernet (or len(subnets) if all subsequents items are a subnet of supernet). )_moduleversionfirstappendlenlast) supernetsubnetsZ subnet_idxrangesr subnetZ prev_subnetZ cur_subnetrrr6/Users/cjl/code/aws-vpc-ipam/lambda/netaddr/ip/sets.py _subtracts(    rccs|sdS|d\}}}|ddD]F\}}}||dkrF||krF|}q"t||t||fV|}|}|}q"t||t||fVdS)aqIterate over sorted_ranges, merging where possible Sorted ranges must be a sorted iterable of (version, first, last) tuples. Merging occurs for pairs like [(4, 10, 42), (4, 43, 100)] which is merged into (4, 10, 100), and leads to return value ( IPAddress(10, 4), IPAddress(100, 4) ), which is suitable input for the iprange_to_cidrs function. Nrr )r) sorted_rangesZcurrent_versionZ current_startZ current_stopZ next_versionZ next_startZ next_stoprrr_iter_merged_ranges8s rc@sHeZdZdZdZdGddZddZd d Zd d Zd dZ ddZ ddZ ddZ e Z ddZddZdHddZdIddZddZdd Zd!d"ZdJd#d$Zd%d&Zd'd(Zd)d*Zd+d,Zd-d.ZeZd/d0Zd1d2ZeZd3d4ZeZ d5d6Z!e!Z"d7d8Z#e#Z$d9d:Z%e%Z&d;d<Z'e(d=d>Z)d?d@Z*e*Z+dAdBZ,dCdDZ-dEdFZ.dS)KIPSetz[ Represents an unordered collection (set) of unique IP addresses and subnets. )_cidrs __weakref__NrcCst|tr|jdi|_nt|tr@tt|d|dd|_nrt|tr^t| d|_nTi|_|dk rg}|D]$}t|t rt ||d}| |qtt |D]}d|j|<qdS)aL Constructor. :param iterable: (optional) an iterable containing IP addresses, subnets or ranges. :param flags: decides which rules are applied to the interpretation of the addr value. See the netaddr.core namespace documentation for supported constant values. TrNflags) isinstancercidrrrdictfromkeysrr iter_cidrsr rrrselfiterabler Z mergeableaddrr"rrr__init__]s$       zIPSet.__init__cCstdd|jDS)z.:return: Pickled state of an ``IPSet`` object.cSsg|] }|qSr) __getstate__.0r"rrr ~sz&IPSet.__getstate__..)tuplerr'rrrr+|szIPSet.__getstate__cCstdd|Dd|_dS)zR :param state: data used to unpickle a pickled ``IPSet`` object. css$|]\}}}t||f|dVqdS))r N)r)r-value prefixlenr rrr sz%IPSet.__setstate__..TN)r#r$r)r'staterrr __setstate__s zIPSet.__setstate__cCsd|j}|j}|j}|j|jjkrH|D]}||jkr(|j|=dSq(ng}|jD]h}|jj|ksR||krlqR|j}|j} ||kr| |kr||qR||krR| |krR|j|=|rt dSqR|D] } |j| =q|jj|j } |j dkr`|j | ?d@} | r| } n| } | |jkrdS|j| =|j|=|j d8_ | d7} |j | ?| >|_ d|j|<qdS)a Same as compact(), but assume that added_network is the only change and that this IPSet was properly compacted before added_network was added. This allows to perform compaction much faster. added_network must already be present in self._cidrs. Nrr T)rrr _prefixlenr widthrrrAssertionErrorr2_valuepreviousnext)r'Z added_networkZ added_firstZ added_lastZ added_versionZpotential_supernetZ to_remover"rritemZ shift_widthZthe_bit candidaterrr_compact_single_networksH         zIPSet._compact_single_networkcCst|j}t|d|_dS)zR Compact internal list of `IPNetwork` objects using a CIDR merge. TN)rrr#r$r'cidrsrrrcompacts z IPSet.compactcCs tddS)z Raises ``TypeError`` if this method is called. .. note:: IPSet objects are not hashable and cannot be used as dictionary keys or as members of other sets. zIP sets are unhashable!N) TypeErrorr0rrr__hash__szIPSet.__hash__cCs>t|}||jkrdS|jr:|jd8_||jkrdSqdS)z :param ip: An IP address or subnet. :return: ``True`` if IP address or subnet is a member of this IP set. Tr F)rrr6)r'iprrrr __contains__s   zIPSet.__contains__cCs t|jS)z9Return True if IPSet contains at least one IP, else False)boolrr0rrr __nonzero__szIPSet.__nonzero__cCstjt|jS)zP :return: an iterator over the IP addresses within this IP set. ) _itertoolschainsortedrr0rrr__iter__szIPSet.__iter__cCs t|jS)zU :return: an iterator over individual IP subnets within this IP set. rJrr0rrrr%szIPSet.iter_cidrscCst|tr)r'r)r Z new_cidrsrrradd s     z IPSet.addcCst|tr4t|d|d}|D]}||q dSt|trLt||d}nt|}||d}d}|jD]}||krlt ||}|}qql|dk r|j|=|D]}d|j|<qdS)a  Removes an IP address or subnet or IPRange from this IP set. Does nothing if it is not already a member. Note that this method behaves more like discard() found in regular Python sets because it doesn't raise KeyError exceptions if the IP address or subnet is question does not exist. It doesn't make sense to fully emulate that behaviour here as IP sets contain groups of individual IP addresses as individual set members using IPNetwork objects. :param addr: An IP address or subnet, or an IPRange. :param flags: decides which rules are applied to the interpretation of the addr value. See the netaddr.core namespace documentation for supported constant values. rrNrT) r!rrremover rrrNrr)r'r)r r@r" remainderZ matching_cidrrrrrO*s(      z IPSet.removecCs|jdS)z Removes and returns an arbitrary IP address or subnet from this IP set. :return: An IP address or subnet. r)rpopitemr0rrrpopbsz IPSet.popcCs||}| S)z :param other: an IP set. :return: ``True`` if this IP set has no elements (IP addresses or subnets) in common with other. Intersection *must* be an empty set. ) intersection)r'otherresultrrr isdisjointks zIPSet.isdisjointcCs|}|j|j|S)z':return: a shallow copy of this IP set.) __class__rrM)r'Zobj_copyrrrcopyvsz IPSet.copycCst|tr:tddtt|jt|jDd|_dSt|ttfrV| |dSt |dsht dg}|D]$}t|t rt ||d}||qptt|j|D]}d|j|<q|dS)a~ Update the contents of this IP set with the union of itself and other IP set. :param iterable: an iterable containing IP addresses, subnets or ranges. :param flags: decides which rules are applied to the interpretation of the addr value. See the netaddr.core namespace documentation for supported constant values. css|] }|VqdS)Nr)r-rDrrrr3szIPSet.update..TNrKzan iterable was expected!r)r!rr#r$rr rrrrNhasattrrBr rrrAr&rrrrM|s*       z IPSet.updatecCs i|_dS)z5Remove all IP addresses and subnets from this IP set.Nrr0rrrclearsz IPSet.clearcCs,z|j|jkWStk r&tYSXdS)z :param other: an IP set :return: ``True`` if this IP set is equivalent to the ``other`` IP set, ``False`` otherwise. NrAttributeErrorNotImplementedr'rTrrr__eq__sz IPSet.__eq__cCs,z|j|jkWStk r&tYSXdS)z :param other: an IP set :return: ``False`` if this IP set is equivalent to the ``other`` IP set, ``True`` otherwise. Nr\r_rrr__ne__sz IPSet.__ne__cCs$t|dstS|j|jko"||S)z :param other: an IP set :return: ``True`` if this IP set is less than the ``other`` IP set, ``False`` otherwise. r)rYr^sizeissubsetr_rrr__lt__s z IPSet.__lt__cCs|jD]}||krdSqdS)z :param other: an IP set. :return: ``True`` if every IP address and subnet in this IP set is found within ``other``. FTrZr'rTr"rrrrcs zIPSet.issubsetcCs$t|dstS|j|jko"||S)z :param other: an IP set. :return: ``True`` if this IP set is greater than the ``other`` IP set, ``False`` otherwise. r)rYr^rb issupersetr_rrr__gt__s z IPSet.__gt__cCs,t|dstS|jD]}||krdSqdS)z :param other: an IP set. :return: ``True`` if every IP address and subnet in other IP set is found within this one. rFT)rYr^rrerrrrfs   zIPSet.issupersetcCs|}|||S)z :param other: an IP set. :return: the union of this IP set and another as a new IP set (combines IP addresses and subnets from both sets). )rXrM)r'rTZip_setrrrunions z IPSet.unionc Csi}t|j}t|j}d}d}t|}t|}||kr||kr||} ||} | | krrd|| <|d7}|d7}q0| | krd|| <|d7}q0| | krd|| <|d7}q0| | kr|d7}q0|d7}q0t} || _| S)z :param other: an IP set. :return: the intersection of this IP set and another as a new IP set. (IP addresses and subnets common to both sets). rTr )rJrrr) r'rT result_cidrsown_nets other_netsown_idx other_idxown_len other_lenown_cur other_currUrrrrSs4       zIPSet.intersectioncCsg}t|j}t|j}d}d}t|}t|}||kr||kr||} ||} | | krj|d7}|d7}q0| | krt| |||}|d7}q0| | krt| |||}|d7}q0| | kr|| jj| j| jf|d7}q0|| jj| j| jf|d7}q0||kr*||} || jj| j| jf|d7}q||kr`||} || jj| j| jf|d7}q*t } t |D]*\} } t | | }|D]}d| j|<qqn| S)z :param other: an IP set. :return: the symmetric difference of this IP set and another as a new IP set (all IP addresses and subnets that are in exactly one of the sets). rr T) rJrrrrr r rrrrr)r'rT result_rangesrjrkrlrmrnrorprqrUstartstopr@r"rrrsymmetric_difference+sd                 zIPSet.symmetric_differencecCsg}i}t|j}t|j}d}d}t|}t|} ||kr|| kr||} ||} | | krn|d7}|d7}q4| | kr|d7}q4| | krt| |||}|d7}q4| | krd|| <|d7}q4|d7}q4||krd|||<|d7}qt|D] \} } t| | D] }d||<qqt}||_|S)z :param other: an IP set. :return: the difference between this IP set and another as a new IP set (all IP addresses and subnets that are in this IP set but not found in the other.) rr T)rJrrrrrr)r'rTrrrirjrkrlrmrnrorprqrsrtr"rUrrr differenceosD          zIPSet.differencecCs|j}|tkrtdt|S)z :return: the cardinality of this IP set (i.e. sum of individual IP addresses). Raises ``IndexError`` if size > maxint (a Python limitation). Use the .size property for subnets of any size. zUrange contains more than %d (sys.maxint) IP addresses!Use the .size property instead.)rbr IndexError)r'rbrrr__len__sz IPSet.__len__cCstdd|jDS)z The cardinality of this IP set (based on the number of individual IP addresses including those implicitly defined in subnets). cSsg|] }|jqSr)rbr,rrrr.szIPSet.size..)sumrr0rrrrbsz IPSet.sizecCsdddt|jDS)z8:return: Python statement to create an equivalent objectz IPSet(%r)cSsg|] }t|qSr)str)r-crrrr.sz"IPSet.__repr__..rLr0rrr__repr__szIPSet.__repr__cCsL|}t|dkrH|dd}|D]"}|d|kr:dS|dd}q$dS)z Returns True if the members of the set form a contiguous IP address range (with no gaps), False otherwise. :return: ``True`` if the ``IPSet`` object is contiguous. r rFrT)r%r)r'r@r:r"rrr iscontiguouss   zIPSet.iscontiguouscCs>|r2|}|sdSt|dd|ddStddS)z Generates an IPRange for this IPSet, if all its members form a single contiguous sequence. Raises ``ValueError`` if the set is not contiguous. :return: An ``IPRange`` for all IPs in the IPSet. NrrzIPSet is not contiguous)r}r%r ValueErrorr?rrripranges z IPSet.iprangeccs4dd|D}t|D]\}}t||VqdS)zGenerate the merged IPRanges for this IPSet. In contrast to self.iprange(), this will work even when the IPSet is not contiguous. Adjacent IPRanges will be merged together, so you get the minimal number of IPRanges. cSsg|]}|jj|j|jfqSr)r r rrr,rrrr.sz'IPSet.iter_ipranges..N)r%rr)r'rrsrtrrr iter_iprangess zIPSet.iter_ipranges)Nr)r)r)r)/__name__ __module__ __qualname____doc__ __slots__r*r+r5r>rArCrErG__bool__rKr%rNrOrRrVrXrMr[r`rardrc__le__rgrf__ge__rh__or__rS__and__ru__xor__rv__sub__rxpropertyrbr|__str__r}rrrrrrrUsX  J  ! 8   #      *B4  r)r itertoolsrH netaddr.iprrrrrrnetaddr.compatrr r rrobjectrrrrrs  (