
    >Tfx                     p   d dl Z d dlmZ d dlmZ d dlmZ d dlmZ d dl	m
Z
 d dlmZ d dlmZ d d	lmZ d d
lmZ d dlT d dlT d dlmZ d dlmZmZ d dlmZmZ d dlmZ d dl m!Z! d dl"m#Z# d dl$m%Z% ddl&m'Z'm(Z(m)Z) dZ* e            Z+ G d de          Z, G d de          Z- G d dej.                  Z/dS )    N)defaultdict)GenericForeignKey)ValidationError)models)Sum)Signal)reverse)gettext_lazy)
ObjectType)*)	PathField)decompile_path_nodeobject_to_path_node)ChangeLoggedModelPrimaryModel)	to_meters)
ColorField)RestrictedQuerySet)WirelessLink   )	FrontPortRearPortPathEndpoint)Cable	CablePathCableTerminationc                       e Zd ZdZ ej         ed          ded          Z ej         ed          de	e	j
                  Z ej        dej        d	dd
          Z ej         ed          dd          Z e ed          d          Z ej         ed          dddd          Z ej         ed          ded          Z ej        dddd          ZdZ G d d          Zddd fd
Zd Zd Zed              Zej        d!             Zed"             Zej        d#             Z fd$Z  fd%Z!d& Z" xZ#S )'r   z6
    A physical connection between two endpoints.
    type2   T)verbose_name
max_lengthchoicesblankstatus)r    r!   r"   defaultztenancy.Tenantcables)to	on_deleterelated_namer#   nulllabeld   )r    r!   r#   color)r    r#   length      )r    
max_digitsdecimal_placesr#   r*   zlength unit
      )r1   r2   r#   r*   )tenantr   c                   >    e Zd ZdZ ed          Z ed          ZdS )
Cable.Metapkcabler&   N)__name__
__module____qualname__ordering_r    verbose_name_plural     7/var/www/html/netbox-4.1.3/netbox/dcim/models/cables.pyMetar7   ]   s0        qzzakkrB   rD   N)a_terminationsb_terminationsc                     t                      j        |i | | j                            d          | _        | j                            d          | _        d| _        |r|| _        |r	|| _        d S d S )Nidr$   F)	super__init____dict__get_pk_orig_status_terminations_modifiedrE   rF   )selfrE   rF   argskwargs	__class__s        rC   rJ   zCable.__init__b   s    $)&))) =$$T** !M--h77&+#  	1"0D 	1"0D	1 	1rB   c                 6    | j         p| j        }| j        pd| S )N#)r9   rM   r+   )rP   r9   s     rC   __str__zCable.__str__s   s#    W z%XXX%rB   c                 0    t          d| j        g          S )Nz
dcim:cable)rQ   )r	   r9   rP   s    rC   get_absolute_urlzCable.get_absolute_urlw   s    |47)4444rB   c                     t          | d          r| j        S | j        sg S d | j                                        D             S )N_a_terminationsc                 F    g | ]}|j         t          j        k    |j        S rA   )	cable_endCableEndChoicesSIDE_Atermination.0cts     rC   
<listcomp>z(Cable.a_terminations.<locals>.<listcomp>   1     
 
 
!P_Pf@f@fBN@f@f@frB   )hasattrr[   r9   terminationsallrX   s    rC   rE   zCable.a_terminationsz   ]    4*++ 	(''w 	I
 
%)%6%:%:%<%<
 
 
 	
rB   c                 `    | j         r| j        t          |          k    rd| _        || _        d S NT)r9   rE   listrO   r[   rP   values     rC   rE   zCable.a_terminations   5    w 	/$-e<<*.D'$rB   c                     t          | d          r| j        S | j        sg S d | j                                        D             S )N_b_terminationsc                 F    g | ]}|j         t          j        k    |j        S rA   )r]   r^   SIDE_Br`   ra   s     rC   rd   z(Cable.b_terminations.<locals>.<listcomp>   re   rB   )rf   rq   r9   rg   rh   rX   s    rC   rF   zCable.b_terminations   ri   rB   c                 `    | j         r| j        t          |          k    rd| _        || _        d S rk   )r9   rF   rl   rO   rq   rm   s     rC   rF   zCable.b_terminations   ro   rB   c                 t   t                                                       | j        #| j        st	          t          d                    | j        j        r*| j        r| j	        st	          t          d                    | j
        r| j        | j	        fD ]Tt                    dk    r?t          fddd          D                       st	          t          d                    U| j        r| j	        r| j        d         j        j        }| j	        d         j        j        }|t                              |          vr1t	          t          d                              ||                    ||k    r]t%          d	 | j        D                       }t%          d
 | j	        D                       }||z  rt	          t          d                    | j        D ]&}t'          | d|                                           '| j	        D ](}t'          | d|                                           'd S d S )Nz/Must specify a unit when setting a cable lengthz;Must define A and B terminations when creating a new cable.r   c              3   ^   K   | ]'}t          |t          d                              V  (dS r   N
isinstancer   )rb   ttermss     rC   	<genexpr>zCable.clean.<locals>.<genexpr>   s8      -_-_PQjDqNN.K.K-_-_-_-_-_-_rB   z@Cannot connect different termination types to same end of cable.r   z5Incompatible termination types: {type_a} and {type_b})type_atype_bc              3   2   K   | ]}|j         	|j         V  d S Nr8   rb   objs     rC   r|   zCable.clean.<locals>.<genexpr>   +      PP3PPPPPPPrB   c              3   2   K   | ]}|j         	|j         V  d S r   r8   r   s     rC   r|   zCable.clean.<locals>.<genexpr>   r   rB   z7A and B terminations cannot connect to the same object.Ar:   r]   r`   B)rI   cleanr.   length_unitr   r?   _stateaddingrE   rF   rO   lenrh   _meta
model_nameCOMPATIBLE_TERMINATION_TYPESrL   formatsetr   )rP   a_typeb_typea_pksb_pksr`   r{   rS   s         @rC   r   zCable.clean   s    ;"4+;"!!$U"V"VWWW; 	dt': 	d$BU 	d!!$a"b"bccc& 	] -t/BC q qu::>>#-_-_-_-_UZ[\[][]U^-_-_-_*_*_>)!,n*o*oppp " t': ,Q/5@,Q/5@!=!A!A&!I!III)QRRYYagpvYww   V##  PP$2EPPPPPEPP$2EPPPPPE -WXX  
  $2 ] ] tsTTTZZ\\\\#2 ] ] tsTTTZZ\\\\=	] 	]:] ]rB   c                    | j         d u }| j        '| j        r t          | j        | j                  | _        nd | _        | j        d| _         t                      j        |i | | j         | _        d | j        	                    d          D             }d | j        	                    d          D             }| j
        r||                                D ])\  }}|j         r|| j        vr|                                 *|                                D ])\  }}|j         r|| j        vr|                                 *| j
        rr| j        D ]1}|j         r||vr$t          | d|                                           2| j        D ]1}|j         r||vr$t          | d|                                           2t                               t$          | |           d S )	N c                     i | ]
}|j         |S rA   r`   ra   s     rC   
<dictcomp>zCable.save.<locals>.<dictcomp>       ___"."___rB   r   )r]   c                     i | ]
}|j         |S rA   r   ra   s     rC   r   zCable.save.<locals>.<dictcomp>   r   rB   r   r   )instancecreated)r9   r.   r   r   _abs_lengthrI   saverM   rg   filterrO   itemsrE   deleterF   r   trace_pathssendr   )	rP   rQ   rR   _createdrE   rF   r`   rc   rS   s	           rC   r   z
Cable.save   s'   7d? ;"t'7"(d6FGGD#D ;!Dd%f%%% 7 `_t7H7O7OZ]7O7^7^_____t7H7O7OZ]7O7^7^___ & 	 #1#7#7#9#9    R>  k9L&L&LIIKKK#1#7#7#9#9    R>  k9L&L&LIIKKK & 	`#2 ` `"~ `N)J)J$43KXXX]]___#2 ` `"~ `N)J)J$43KXXX]]___x@@@@@rB   c                 J    t           j                            | j                  S r   )LinkStatusChoicescolorsrL   r$   rX   s    rC   get_status_colorzCable.get_status_color   s     '++DK888rB   )$r;   r<   r=   __doc__r   	CharFieldr?   CableTypeChoicesr   r   STATUS_CONNECTEDr$   
ForeignKeyPROTECTr5   r+   r   r-   DecimalFieldr.   CableLengthUnitChoicesr   r   clone_fieldsrD   rJ   rV   rY   propertyrE   setterrF   r   r   r   __classcell__rS   s   @rC   r   r   &   s         6QvYY 	  D VQx[[!!2	  F V.  F FQwZZ  E
 JQwZZ  E !V Qx[[  F #&"Q}%%&	  K &&%	  K 'L* * * * * * * *
 .2$ 1 1 1 1 1 1 1"& & &5 5 5 

 

 X

 % % %
 

 

 X

 % % %
(] (] (] (] (]T(A (A (A (A (AT9 9 9 9 9 9 9rB   r   c                   ,    e Zd ZdZ ej        dej        d          Z ej        de	 e
d                    Z ej        deej        d	
          Z ej                    Z edd          Z ej        dej        dd          Z ej        dej        dd          Z ej        dej        dd          Z ej        dej        dd          Z ej                    Z G d d          Zd Z fdZ fdZ fdZd Zde_          fdZ! xZ"S )r   zv
    A mapping between side A or B of a Cable and a terminating object (e.g. an Interface or CircuitTermination).
    z
dcim.Cablerg   )r'   r(   r)   r   end)r!   r"   r    zcontenttypes.ContentType+)r'   limit_choices_tor(   r)   termination_typetermination_id)ct_fieldfk_fieldzdcim.DeviceT)r'   r(   r#   r*   z	dcim.Rackzdcim.Locationz	dcim.Sitec                       e Zd ZdZ ej        d          fZ ej        dd          fZ e	d          Z
 e	d          ZdS )	CableTermination.Meta)r:   r]   r9   r   r   )fieldsz*%(app_label)s_%(class)s_unique_termination)r   namezcable terminationzcable terminationsN)r;   r<   r=   r>   r   IndexindexesUniqueConstraintconstraintsr?   r    r@   rA   rB   rC   rD   r   .  sx        /FL FGGG
 $F#=A  
 q,--a 455rB   rD   c                 &    d| j          d| j         S )NzCable z to )r:   r`   rX   s    rC   rV   zCableTermination.__str__<  s    :
::(8:::rB   c           
         t                                                       t          j                            | j        | j                  }| j        j        r|	                    | j                  }|
                                }|Vt          t          d                    | j        j        | j        j        | j        |j        j                                      | j        j        dk    rZ| j        j        t$          v rGt          t          d                              | j                                                            | j        j        dk    r(| j        j        t          t          d	                    d S d S )
Nr   )r:   zVDuplicate termination found for {app_label}.{model} {termination_id}: cable {cable_pk})	app_labelmodelr   cable_pk	interfacez8Cables cannot be terminated to {type_display} interfaces)type_displaycircuitterminationzFCircuit terminations attached to a provider network may not be cabled.)rI   r   r   objectsr   r   r   r:   r9   excludefirstr   r?   r   r   r   r`   r   NONCONNECTABLE_IFACE_TYPESget_type_displayprovider_network)rP   qsexisting_terminationrS   s      rC   r   zCableTermination.clean?  s}    %,,!2. - 
 
 := 	.$*--B!xxzz+!jqq"3=/5#'#617:	 r        &+55$:J:OSm:m:m!LMMTT!%!1!B!B!D!D U      &*>>>4CSCdCp!!$l"m"mnnn ?>CpCprB   c                 @   |                                    t                      j        |i | | j        j        j        j                            | j                  }|	                                 | j
        |_
        | j        |_        |                                 d S )Nr8   )cache_related_objectsrI   r   r`   r   r   r   rL   r   snapshotr:   r]   rP   rQ   rR   r`   rS   s       rC   r   zCableTermination.save`  s     	""$$$d%f%%% &,2:>>$BU>VV J $rB   c                    | j         j        j        j                            | j                  }|                                 d |_        d|_        |	                                  t                      j        |i | d S )Nr8   r   )r`   r   r   r   rL   r   r   r:   r]   r   rI   r   r   s       rC   r   zCableTermination.deleten  s     &,2:>>$BU>VV  "''''''rB   c                    | j         J t          | j         dd          rU| j         j        | _        | j         j        j        | _        | j         j        j        | _        | j         j        j        | _	        dS t          | j         dd          r?| j         j        | _        | j         j        j        | _        | j         j        j        | _	        dS t          | j         dd          r| j         j        | _	        dS dS )z
        Cache objects related to the termination (e.g. device, rack, site) directly on the object to
        enable efficient filtering.
        Ndeviceracksite)
r`   getattrr   _devicer   _racklocation	_locationr   _siterX   s    rC   r   z&CableTermination.cache_related_objectsy  s    
 +++ 4#Xt44 	/+2DL)05DJ!-4=DN)05DJJJ T%vt44 	/).DJ!-2;DN).3DJJJ T%vt44 	/).DJJJ	/ 	/rB   c                 b    t                                          |          }| j        |_        |S r   )rI   to_objectchanger`   related_object)rP   actionobjectchangerS   s      rC   r   z CableTermination.to_objectchange  s+    ww..v66&*&6#rB   )#r;   r<   r=   r   r   r   CASCADEr:   r   r^   r?   r]   CABLE_TERMINATION_MODELSr   r   PositiveBigIntegerFieldr   r   r`   r   r   r   r   r   
as_managerr   rD   rV   r   r   r   r   alters_datar   r   r   s   @rC   r   r      sF         F.#  E
 ! QuXX  I
 )v(%1.	   4V355N###!  K  f.	  G F.	  E "!.	  I F.	  E , +--G6 6 6 6 6 6 6 6; ; ;o o o o oB    	( 	( 	( 	( 	(/ / /. )-%        rB   r   c                       e Zd ZdZ ej         ed          e          Z ej	         ed          d          Z
 ej	         ed          d          Z ej	         ed          d          Z e            ZdZ G d	 d
          Zd Z fdZed             Zed             Zed             Zed             Zed             Zed             Zed             Zd Zde_        d Zd Zd Z d Z!d Z" xZ#S )r   aH  
    A CablePath instance represents the physical path from a set of origin nodes to a set of destination nodes,
    including all intermediate elements.

    `path` contains the ordered set of nodes, arranged in lists of (type, ID) tuples. (Each cable in the path can
    terminate to one or more objects.)  For example, consider the following
    topology:

                     A                              B                              C
        Interface 1 --- Front Port 1 | Rear Port 1 --- Rear Port 2 | Front Port 3 --- Interface 2
                        Front Port 2                                 Front Port 4

    This path would be expressed as:

    CablePath(
        path = [
            [Interface 1],
            [Cable A],
            [Front Port 1, Front Port 2],
            [Rear Port 1],
            [Cable B],
            [Rear Port 2],
            [Front Port 3, Front Port 4],
            [Cable C],
            [Interface 2],
        ]
    )

    `is_active` is set to True only if every Cable within the path has a status of "connected". `is_complete` is True
    if the instance represents a complete end-to-end path from origin(s) to destination(s). `is_split` is True if the
    path diverges across multiple cables.

    `_nodes` retains a flattened list of all nodes within the path to enable simple filtering.
    path)r    r%   z	is activeFzis completezis splitTc                   :    e Zd Z ed          Z ed          ZdS )CablePath.Metaz
cable pathzcable pathsN)r;   r<   r=   r?   r    r@   rA   rB   rC   rD   r     s-        qa..rB   rD   c                 B    d| j          dt          | j                   dS )NzPath #z: z hops)r9   r   r   rX   s    rC   rV   zCablePath.__str__  s%    8883ty>>8888rB   c                 L   t          t          j        | j                   | _         t                      j        |i | | j                                        }d | j        d         D             }|j	        
                    |                              | j                   d S )Nc                 8    g | ]}t          |          d          S )r   )r   rb   nodes     rC   rd   z"CablePath.save.<locals>.<listcomp>  s&    LLLt)$//2LLLrB   r   pk__in)_path)rl   	itertoolschainr   _nodesrI   r   origin_typemodel_classr   r   updater9   )rP   rQ   rR   origin_model
origin_idsrS   s        rC   r   zCablePath.save  s     9?DI677d%f%%% '3355LLty|LLL
##:#66==DG=LLLLLrB   c                     | j         rBt          | j         d         d                   \  }}t          j                            |          S d S )Nr   )r   r   r   r   
get_for_idrP   ct_idr?   s      rC   r  zCablePath.origin_type  sH    9 	8*49Q<?;;HE1%00777	8 	8rB   c                     | j         rBt          | j        d         d                   \  }}t          j                            |          S d S )Nr   )is_completer   r   r   r   r  r  s      rC   destination_typezCablePath.destination_type  sJ     	8*49R=+;<<HE1%00777	8 	8rB   c                 b    t          | d          s|                                 | _        | j        S )zx
        Cache and return the complete path as lists of objects, derived from their annotation within the path.
        _path_objects)rf   	_get_pathr  rX   s    rC   path_objectszCablePath.path_objects  s1    
 t_-- 	2!%!1!1D!!rB   c                     | j         d         S )z9
        Return the list of originating objects.
        r   )r  rX   s    rC   originszCablePath.origins  s    
  ##rB   c                 .    | j         sg S | j        d         S )zR
        Return the list of destination objects, if the path is complete.
        r  )r  r  rX   s    rC   destinationszCablePath.destinations  s"    
  	I $$rB   c                 J    t          t          | j                  dz            S )N   )intr   r   rX   s    rC   segment_countzCablePath.segment_count  s    3ty>>A%&&&rB   c                    ddl m} sdS t                    dk    r%t          fddd         D                       sJ g }g }d}d}d}r~t          fddd         D                       sJ t	          d         t
                    sJt          fd	dd         D                       sJ t          fd
dd         D                       sJ t          t          d D                                 dk    r,|r*t                    t          |d                   k    rd}n|                    d D                        d D             t                    dk    rt          |          dk    rdS nIt          d D                       sJ t          fdD                       sJ d D             }t          |          dk    rd}d}g }	D ]5}
t          |
          |	vr"|	                    t          |
                     6|                    |	           d D             }t          d |D                       rd}t	          d         t                    rt          j                            d                   }t          j                            |d D                       }t!                      }|D ]*}|j        dk    rdnd}|t!          |j        |          z  }+t          j                            |          }d |D             nfdD             t          fddd         D                       sd}d}no|                    d D                        snLt	          d         t&                    rqt(          j                            d D                       }t          |          dk    s|d         j        dk    r|                    d D                        |nt	          d         t(                    rWt                    dk    r>d         j        dk    r-t&          j                            d  D             d!          }nt                    dk    r|r|                                }t                    t          |          k    sJ t!                      }D ]/}|                                }|t!          |j        |"          z  }0|t!                      usJ t&          j                            |          }nE|r?t&          j                            d         j        |                                #          }nd}nQ|nJt	          d         |          rt                    dk    rd}n |j                            d         j        d         j        dk    rd$nd%                                          }|n|j        r;|                    t          |          gt          |j                  gg           d}n|j        r@|j        s9|                    t          |          gt          |j                  gg           nH|gnAt          fd&dd         D                       rd}nt                    dk    rd}nd}d}n~ | ||||'          S )(a>  
        Create a new CablePath instance as traced from the given termination objects. These can be any object to which a
        Cable or WirelessLink connects (interfaces, console ports, circuit termination, etc.). All terminations must be
        of the same type and must belong to the same parent object.
        r   CircuitTerminationNr   c              3   D   K   | ]}|j         d          j         k    V  dS rw   linkrb   rz   rg   s     rC   r|   z(CablePath.from_origin.<locals>.<genexpr>  s1      PP!qva!55PPPPPPrB   FTc              3   ^   K   | ]'}t          |t          d                              V  (dS rw   rx   r   s     rC   r|   z(CablePath.from_origin.<locals>.<genexpr>$  s9      VVz!T,q/%:%:;;VVVVVVrB   c              3   ^   K   | ]'}t          |t          d                              V  (dS rw   rx   r   s     rC   r|   z(CablePath.from_origin.<locals>.<genexpr>(  s9      ZZA:al1o)>)>??ZZZZZZrB   c              3   D   K   | ]}|j         d          j         k    V  dS rw   )parent_objectr   s     rC   r|   z(CablePath.from_origin.<locals>.<genexpr>)  s2      ffPQ1?l1o.KKffffffrB   c              3   $   K   | ]}|j         V  d S r   r  rb   rz   s     rC   r|   z(CablePath.from_origin.<locals>.<genexpr>-  s$      44!qv444444rB   r  c                 ,    g | ]}t          |          S rA   r   r&  s     rC   rd   z)CablePath.from_origin.<locals>.<listcomp>4  s.       +,#A&&  rB   c                 *    g | ]}|j         	|j         S r   r  rb   r`   s     rC   rd   z)CablePath.from_origin.<locals>.<listcomp>9  s#    fff+IYIe[%IeIeIerB   c              3   P   K   | ]!}t          |          t          t          fv V  "d S r   )r   r   r   rb   r  s     rC   r|   z(CablePath.from_origin.<locals>.<genexpr>@  s2      MMttDzze\%::MMMMMMrB   c              3   ^   K   | ]'}t          |t          d                              V  (dS rw   rx   )rb   r  linkss     rC   r|   z(CablePath.from_origin.<locals>.<genexpr>A  s7      JJDz$U1X77JJJJJJrB   c                 *    g | ]}|j         	|j         S r   r  r*  s     rC   rd   z)CablePath.from_origin.<locals>.<listcomp>D  s$    )w)w)w{^i^n^v+*:^v^v^vrB   c                 F    g | ]}|j         t          j        k    |j         S rA   )r$   r   r   r,  s     rC   rd   z)CablePath.from_origin.<locals>.<listcomp>Q  s*    oooDT[L]Ln=n=nDK=n=n=nrB   c                 .    g | ]}|t           j        k    S rA   )r   r   )rb   r$   s     rC   rd   z)CablePath.from_origin.<locals>.<listcomp>R  s!    \\\VF/@@\\\rB   c                     g | ]	}|j         
S rA   r8   r&  s     rC   rd   z)CablePath.from_origin.<locals>.<listcomp>Z  s    'C'C'C'C'C'CrB   )r   termination_id__inr   r   )r:   r]   c                     g | ]	}|j         
S rA   r   ra   s     rC   rd   z)CablePath.from_origin.<locals>.<listcomp>c  s    &Z&Z&Z"r~&Z&Z&ZrB   c                 J    g | ]}|j         d          u r|j        n|j          S )r   )interface_ainterface_b)rb   r  rg   s     rC   rd   z)CablePath.from_origin.<locals>.<listcomp>f  sC     ' ' 'fj(8LO(K(KD$$QUQa' ' 'rB   c              3   ^   K   | ]'}t          |t          d                              V  (dS rw   rx   rb   rz   remote_terminationss     rC   r|   z(CablePath.from_origin.<locals>.<genexpr>k  ;      ddqz!T*=a*@%A%ABBddddddrB   c                 0    g | ]}|t          |          S r   r(  r&  s     rC   rd   z)CablePath.from_origin.<locals>.<listcomp>q  s)       +,q}#A&&}}}rB   c                     g | ]	}|j         
S rA   rear_port_idr&  s     rC   rd   z)CablePath.from_origin.<locals>.<listcomp>|  s    HHHqANHHHrB   r   c                     g | ]	}|j         
S rA   )rear_port_positionrb   fps     rC   rd   z)CablePath.from_origin.<locals>.<listcomp>  s    *_*_*_R2+@*_*_*_rB   c                     g | ]	}|j         
S rA   r8   )rb   rps     rC   rd   z)CablePath.from_origin.<locals>.<listcomp>  s    )N)N)NB"%)N)N)NrB   )rear_port_id__inrA  )r?  rA  )r?  rear_port_position__inZ)circuit	term_sidec              3   ^   K   | ]'}t          |t          d                              V  (dS rw   rx   r9  s     rC   r|   z(CablePath.from_origin.<locals>.<genexpr>  r;  rB   )r   r  	is_activeis_split)circuits.modelsr  r   rh   ry   r   r   appendr   anyr   r   r   get_for_modelr   r   Qr]   r:   r   r   	positionspopr9   rI  rJ  r   r   extendr   )clsrg   r  r   position_stackr  rL  rM  not_connected_terminationsr&   r  links_statusr   local_cable_terminationsq_filterlctr]   remote_cable_terminations
rear_portsfront_portsrS  rtpositioncircuit_terminationr.  r:  s    `                      @@rC   from_originzCablePath.from_origin  s    	766666 	4 |q  PPPP|ABB?OPPPPPPPP	 j	 VVVV\RSRTRTEUVVVVVVVV l1o|<< gZZZZVWVXVXIYZZZZZZZZffffUabcbdbdUeffffffff 344|444445599" :'*<'8'8Cr@R<S<S'S'S KK  0<     
 gffffE5zzQt99>>4MMuMMMMMMMMJJJJEJJJJJJJJ *x)wl)w)w)w&-..22# F = =&t,,F::MM"5d";";<<<KK poEoooL\\|\\\]] "!	 %(E** #-#5#C#CLQRO#T#T +;+C+J+J%5'C'Cl'C'C'C ,K , ,(
 333 H HC'*}';';I	Y G G GGHH,<,D,K,KH,U,U)&Z&Z@Y&Z&Z&Z##' ' ' 'ns' ' '#
 ddddL_`a`b`bLcddddd # KK  0C     
 ' -a0)<< R%-44HH4GHHH 5  
 z??Q&&*Q-*AA*E*E"))*_*_K^*_*_*_```)/2H== H*++q005H5K5UYZ5Z5Z"+"3":":)N)N:M)N)N)N+, #; # #KK
 ,--11n1 . 2 2 4 4I 233s9~~EEEE  !ssH1 W W#,==?? A25X$V$V$VV#133...."+"3":":8"D"DKK# "+"3":":%8%;%>/=/A/A/C/C #; # #KK  $H*/24FGG '*++a//#H&8&@&G&G/2:%8%;%E%L%LccRU 'H ' ' %'' $ '.(9 KK,-@AAB,-@-QRRS!    #'K(- 6I6O KK,-@AAB,-@-EFFG!     34 ddddL_`a`b`bLcddddd $"&KK,--22"'KK #(K#HU  j	X s#	
 
 
 	
rB   c                     |                      | j                  }|rF|j        | _        |j        | _        |j        | _        |j        | _        |                                  dS |                                  dS )zX
        Retrace the path from the currently-defined originating termination(s)
        N)rc  r  r   r  rL  rM  r   r   )rP   _news     rC   retracezCablePath.retrace  si     -- 		DI#/D!^DN MDMIIKKKKKKKMMMMMrB   c                    t          t                    }| j        D ]/}t          |          \  }}||                             |           0i }|                                D ]\  }}t          j                            |          	                                }|j        
                    |          }t          |d          r|                    d          }d |D             ||<   g }	| j        D ]b}
g }|
D ]F}t          |          \  }}	 |                    ||         |                    7# t          $ r Y Cw xY w|	                    |           c|	S )zB
        Return the path as a list of prefetched objects.
        r   r   c                     i | ]
}|j         |S rA   )rH   r   s     rC   r   z'CablePath._get_path.<locals>.<dictcomp>  s)     ! ! ! #! ! !rB   )r   rl   r   r   rO  r   r   r   r  r  r   rf   prefetch_relatedr   KeyError)rP   to_prefetchr   r	  	object_id
prefetched
object_idsr  querysetr   stepnodess               rC   r  zCablePath._get_path  s   
 "$''K 	1 	1D2488E9%%i0000 
!,!2!2!4!4 	 	E:$,77>>JJLLK"*111DDH{H-- ?#44X>>! !'/! ! !Ju
 I 		 		DE  #6t#<#< yLLE!29!=>>>>   D KKs   !D..
D;:D;c                     t           j                            t                    j        }g }| j        D ]/}t          |          \  }}||k    r|                    |           0|S )z7
        Return all Cable IDs within the path.
        )r   r   rQ  r   r9   r   r   rO  )rP   cable_ct	cable_idsr   rc   rH   s         rC   get_cable_idszCablePath.get_cable_ids  sh     %33E::=	K 	% 	%D(..FBX~~  $$$rB   c                    |                                  }t          j                            |d          }|                    t          d                    d         }t          |          t          |          k    }||fS )z
        Return a tuple containing the sum of the length of each cable in the path
        and a flag indicating whether the length is definitive.
        F)id__in_abs_length__isnullr   )totalry  )ru  r   r   r   	aggregater   r   )rP   rt  r&   total_lengthis_definitives        rC   get_total_lengthzCablePath.get_total_length  ss    
 &&((	%%YE%RR''c-.@.@'AA'JFs9~~5]**rB   c                 v   ddl m} | j        d         }t          |d                   t          u r t
          j                            |          S t          |d                   t
          u r*t          j                            d |D                       S t          |d                   |u rd |D             S dS )	K
        Return all available next segments in a split cable path.
        r   r  r  )rear_port__inc                     g | ]	}|j         
S rA   r>  rB  s     rC   rd   z-CablePath.get_split_nodes.<locals>.<listcomp>.  s    2S2S2Sr2?2S2S2SrB   r   c                 6    g | ]}|                                 S rA   )get_peer_terminationra   s     rC   rd   z-CablePath.get_split_nodes.<locals>.<listcomp>1  s1       .0''))  rB   N)rN  r  r  r   r   r   r   r   )rP   r  rq  s      rC   get_split_nodeszCablePath.get_split_nodes!  s     	766666!"% a>>X%%$++%+@@@ %(^^y((#**2S2SU2S2S2S*TTT%(^^111 49    21rB   c                     ddl m} g }| j        D ]E}t          |d                   t          t
          |fv r|                    d |D                        F|S )r  r   r  c                      g | ]}|j         	|S r   r  r   s     rC   rd   z2CablePath.get_asymmetric_nodes.<locals>.<listcomp>=  s    (U(U(U$49CTCTCTCTrB   )rN  r  r  r   r   r   rU  )rP   r  asymmetric_nodesrq  s       rC   get_asymmetric_nodeszCablePath.get_asymmetric_nodes5  sw     	766666& 	W 	WEE!H~~(I7I!JJJ ''(U(U%(U(U(UVVVrB   )$r;   r<   r=   r   r   	JSONFieldr?   rl   r   BooleanFieldrL  r  rM  r   r   _netbox_privaterD   rV   r   r   r  r  r  r  r  r  classmethodrc  rf  r   r  ru  r}  r  r  r   r   s   @rC   r   r     s]       ! !D 6QvYY  D $#Q{^^  I &&%Q}%%  K #v"Qz]]  H Y[[FO/ / / / / / / /9 9 9
M 
M 
M 
M 
M 8 8 X8
 8 8 X8
 " " X" $ $ X$ % % X% ' ' X' F
 F
 [F
P   G" " "H  
+ 
+ 
+  (
  
  
  
  
  
  
 rB   r   )0r   collectionsr   "django.contrib.contenttypes.fieldsr   django.core.exceptionsr   	django.dbr   django.db.modelsr   django.dispatchr   django.urlsr	   django.utils.translationr
   r?   core.modelsr   dcim.choicesdcim.constantsdcim.fieldsr   
dcim.utilsr   r   netbox.modelsr   r   utilities.conversionr   utilities.fieldsr   utilities.querysetsr   wireless.modelsr   device_componentsr   r   r   __all__r   r   r   Modelr   rA   rB   rC   <module>r     s.       # # # # # # @ @ @ @ @ @ 2 2 2 2 2 2                   " " " " " "       6 6 6 6 6 6 " " " " " "         ! ! ! ! ! ! ? ? ? ? ? ? ? ? 9 9 9 9 9 9 9 9 * * * * * * ' ' ' ' ' ' 2 2 2 2 2 2 ( ( ( ( ( ( @ @ @ @ @ @ @ @ @ @ fhhO9 O9 O9 O9 O9L O9 O9 O9d] ] ] ] ]( ] ] ]@g  g  g  g  g  g  g  g  g  g rB   