1515from dcim .utils import decompile_path_node , object_to_path_node
1616from netbox .models import ChangeLoggedModel , PrimaryModel
1717from utilities .conversion import to_meters
18+ from utilities .exceptions import AbortRequest
1819from utilities .fields import ColorField
1920from utilities .querysets import RestrictedQuerySet
2021from wireless .models import WirelessLink
2627 'CableTermination' ,
2728)
2829
30+ from ..exceptions import UnsupportedCablePath
2931
3032trace_paths = Signal ()
3133
@@ -236,8 +238,10 @@ def save(self, *args, **kwargs):
236238 for termination in self .b_terminations :
237239 if not termination .pk or termination not in b_terminations :
238240 CableTermination (cable = self , cable_end = 'B' , termination = termination ).save ()
239-
240- trace_paths .send (Cable , instance = self , created = _created )
241+ try :
242+ trace_paths .send (Cable , instance = self , created = _created )
243+ except UnsupportedCablePath as e :
244+ raise AbortRequest (e )
241245
242246 def get_status_color (self ):
243247 return LinkStatusChoices .colors .get (self .status )
@@ -531,8 +535,8 @@ def from_origin(cls, terminations):
531535 return None
532536
533537 # Ensure all originating terminations are attached to the same link
534- if len (terminations ) > 1 :
535- assert all ( t . link == terminations [ 0 ]. link for t in terminations [ 1 :] )
538+ if len (terminations ) > 1 and not all ( t . link == terminations [ 0 ]. link for t in terminations [ 1 :]) :
539+ raise UnsupportedCablePath ( _ ( "All originating terminations must be attached to the same link" ) )
536540
537541 path = []
538542 position_stack = []
@@ -543,12 +547,13 @@ def from_origin(cls, terminations):
543547 while terminations :
544548
545549 # Terminations must all be of the same type
546- assert all (isinstance (t , type (terminations [0 ])) for t in terminations [1 :])
550+ if not all (isinstance (t , type (terminations [0 ])) for t in terminations [1 :]):
551+ raise UnsupportedCablePath (_ ("All mid-span terminations must have the same termination type" ))
547552
548553 # All mid-span terminations must all be attached to the same device
549- if not isinstance (terminations [0 ], PathEndpoint ):
550- assert all (isinstance ( t , type ( terminations [0 ])) for t in terminations [1 :])
551- assert all ( t . parent_object == terminations [ 0 ]. parent_object for t in terminations [ 1 :] )
554+ if ( not isinstance (terminations [0 ], PathEndpoint ) and not
555+ all (t . parent_object == terminations [0 ]. parent_object for t in terminations [1 :])):
556+ raise UnsupportedCablePath ( _ ( "All mid-span terminations must have the same parent object" ) )
552557
553558 # Check for a split path (e.g. rear port fanning out to multiple front ports with
554559 # different cables attached)
@@ -571,8 +576,10 @@ def from_origin(cls, terminations):
571576 return None
572577 # Otherwise, halt the trace if no link exists
573578 break
574- assert all (type (link ) in (Cable , WirelessLink ) for link in links )
575- assert all (isinstance (link , type (links [0 ])) for link in links )
579+ if not all (type (link ) in (Cable , WirelessLink ) for link in links ):
580+ raise UnsupportedCablePath (_ ("All links must be cable or wireless" ))
581+ if not all (isinstance (link , type (links [0 ])) for link in links ):
582+ raise UnsupportedCablePath (_ ("All links must match first link type" ))
576583
577584 # Step 3: Record asymmetric paths as split
578585 not_connected_terminations = [termination .link for termination in terminations if termination .link is None ]
@@ -653,14 +660,18 @@ def from_origin(cls, terminations):
653660 positions = position_stack .pop ()
654661
655662 # Ensure we have a number of positions equal to the amount of remote terminations
656- assert len (remote_terminations ) == len (positions )
663+ if len (remote_terminations ) != len (positions ):
664+ raise UnsupportedCablePath (
665+ _ ("All positions counts within the path on opposite ends of links must match" )
666+ )
657667
658668 # Get our front ports
659669 q_filter = Q ()
660670 for rt in remote_terminations :
661671 position = positions .pop ()
662672 q_filter |= Q (rear_port_id = rt .pk , rear_port_position = position )
663- assert q_filter is not Q ()
673+ if q_filter is Q ():
674+ raise UnsupportedCablePath (_ ("Remote termination position filter is missing" ))
664675 front_ports = FrontPort .objects .filter (q_filter )
665676 # Obtain the individual front ports based on the termination and position
666677 elif position_stack :
0 commit comments