@@ -534,9 +534,153 @@ def visit_Assign(self, node: ast.Assign) -> None:
534534 target = node .targets [0 ]
535535 self ._handle_unpacking_target (target , value )
536536
537- def _handle_unpacking_target (self , target : ast .AST , value : t .Any ) -> None :
537+ def _handle_name_target (self , target : ast .Name , value : t .Any ) -> None :
538+ """Handle simple name assignment with scope handling.
539+
540+ Args:
541+ target: Name AST node
542+ value: Value to assign
543+ """
544+ self ._set_name_value (target .id , value )
545+
546+ def _handle_attribute_target (
547+ self , target : ast .Attribute , value : t .Any
548+ ) -> None :
549+ """Handle attribute assignment (e.g., self.x = value).
550+
551+ Args:
552+ target: Attribute AST node
553+ value: Value to assign
554+ """
555+ obj = self .visit (target .value )
556+ setattr (obj , target .attr , value )
557+
558+ def _handle_subscript_target (
559+ self , target : ast .Subscript , value : t .Any
560+ ) -> None :
561+ """Handle subscript assignment (e.g., lst[0] = value).
562+
563+ Args:
564+ target: Subscript AST node
565+ value: Value to assign
566+ """
567+ container = self .visit (target .value )
568+ index = self .visit (target .slice )
569+ container [index ] = value
570+
571+ def _handle_starred_unpacking (
572+ self ,
573+ target_elts : list [ast .expr ],
574+ value : t .Any ,
575+ star_index : int ,
576+ starred_target : ast .Starred ,
577+ ) -> None :
578+ """Handle starred unpacking in sequence assignments.
579+
580+ Args:
581+ target_elts: List of target elements
582+ value: Value being unpacked
583+ star_index: Index of the starred expression
584+ starred_target: The starred target node
585+
586+ Raises:
587+ ValueError: If there are not enough values to unpack
588+ UnsupportedUnpackingError: If unpacking pattern is not supported
589+ """
590+ iter_value = iter (value )
591+
592+ # Handle elements before the starred expression
593+ before_elements = target_elts [:star_index ]
594+ for tgt in before_elements :
595+ try :
596+ self ._handle_unpacking_target (tgt , next (iter_value ))
597+ except StopIteration as e :
598+ raise ValueError ("Not enough values to unpack" ) from e
599+
600+ # Collect remaining elements for the starred target
601+ starred_values = list (iter_value )
602+
603+ # Calculate how many elements should be in the starred part
604+ after_star_count = len (target_elts ) - star_index - 1
605+
606+ # If there are more elements after the starred part
607+ if after_star_count > 0 :
608+ # Make sure there are enough elements
609+ if len (starred_values ) < after_star_count :
610+ raise ValueError ("Not enough values to unpack" )
611+
612+ # Separate starred values
613+ starred_list = starred_values [:- after_star_count ]
614+ after_star_values = starred_values [- after_star_count :]
615+
616+ # Assign starred target
617+ if isinstance (starred_target .value , ast .Name ):
618+ self ._set_name_value (starred_target .value .id , starred_list )
619+
620+ # Assign elements after starred
621+ after_elements = target_elts [star_index + 1 :]
622+ for tgt , val in zip (after_elements , after_star_values ):
623+ self ._handle_unpacking_target (tgt , val )
624+ else :
625+ # If no elements after starred, just assign the rest
626+ # to the starred target
627+ if isinstance (starred_target .value , ast .Name ):
628+ self ._set_name_value (starred_target .value .id , starred_values )
629+
630+ def _handle_sequence_unpacking (
631+ self ,
632+ target : ast .Tuple | ast .List ,
633+ value : t .Any ,
634+ ) -> None :
635+ """Handle sequence (tuple/list) unpacking.
636+
637+ Args:
638+ target: Tuple or List AST node
639+ value: Value to unpack
640+
641+ Raises:
642+ ValueError: If value cannot be unpacked
643+ UnsupportedUnpackingError: If unpacking pattern is not supported
538644 """
539- Handle different types of unpacking targets.
645+ try :
646+ if not hasattr (value , "__iter__" ):
647+ raise ValueError ("Cannot unpack non-iterable value" )
648+
649+ # Check for starred expressions (extended unpacking)
650+ starred_indices = [
651+ i
652+ for i , elt in enumerate (target .elts )
653+ if isinstance (elt , ast .Starred )
654+ ]
655+
656+ if len (starred_indices ) > 1 :
657+ raise UnsupportedUnpackingError (
658+ "Cannot use multiple starred expressions in assignment"
659+ )
660+
661+ if starred_indices :
662+ # Handle starred unpacking
663+ star_index = starred_indices [0 ]
664+ starred_target = t .cast (ast .Starred , target .elts [star_index ])
665+ self ._handle_starred_unpacking (
666+ target .elts , value , star_index , starred_target
667+ )
668+ else :
669+ # Standard unpacking without starred expression
670+ value_list = list (value )
671+ if len (value_list ) < len (target .elts ):
672+ raise ValueError ("Not enough values to unpack" )
673+ elif len (value_list ) > len (target .elts ):
674+ raise ValueError ("Too many values to unpack" )
675+
676+ # Unpack each element
677+ for tgt , val in zip (target .elts , value ):
678+ self ._handle_unpacking_target (tgt , val )
679+ except (TypeError , ValueError ) as e :
680+ raise UnsupportedUnpackingError (str (e )) from e
681+
682+ def _handle_unpacking_target (self , target : ast .AST , value : t .Any ) -> None :
683+ """Handle different types of unpacking targets.
540684
541685 Args:
542686 target: AST node representing the unpacking target
@@ -547,102 +691,13 @@ def _handle_unpacking_target(self, target: ast.AST, value: t.Any) -> None:
547691 encountered
548692 """
549693 if isinstance (target , ast .Name ):
550- # Simple name assignment with scope handling
551- self ._set_name_value (target .id , value )
694+ self ._handle_name_target (target , value )
552695 elif isinstance (target , ast .Attribute ):
553- # Handle attribute assignment (e.g., self.x = value)
554- obj = self .visit (target .value )
555- setattr (obj , target .attr , value )
696+ self ._handle_attribute_target (target , value )
556697 elif isinstance (target , ast .Subscript ):
557- # Handle subscript assignment (e.g., lst[0] = value)
558- container = self .visit (target .value )
559- index = self .visit (target .slice )
560- container [index ] = value
698+ self ._handle_subscript_target (target , value )
561699 elif isinstance (target , (ast .Tuple , ast .List )):
562- # Tuple or list unpacking
563- try :
564- # Unpack the value
565- if not hasattr (value , "__iter__" ):
566- raise ValueError ("Cannot unpack non-iterable value" )
567-
568- iter_value = iter (value )
569-
570- # Check for starred expressions (extended unpacking)
571- starred_indices = [
572- i
573- for i , elt in enumerate (target .elts )
574- if isinstance (elt , ast .Starred )
575- ]
576-
577- if len (starred_indices ) > 1 :
578- raise UnsupportedUnpackingError (
579- "Cannot use multiple starred expressions in assignment"
580- )
581-
582- if starred_indices :
583- # Handle starred unpacking
584- star_index = starred_indices [0 ]
585- starred_target = t .cast (
586- ast .Starred , target .elts [star_index ]
587- )
588-
589- # Handle elements before the starred expression
590- before_elements = target .elts [:star_index ]
591- for tgt in before_elements :
592- try :
593- self ._handle_unpacking_target (tgt , next (iter_value ))
594- except StopIteration as e :
595- raise ValueError (
596- "Not enough values to unpack"
597- ) from e
598-
599- # Collect remaining elements for the starred target
600- starred_values = list (iter_value )
601-
602- # Calculate how many elements should be in the starred part
603- # after the current group
604- after_star_count = len (target .elts ) - star_index - 1
605-
606- # If there are more elements after the starred part
607- if after_star_count > 0 :
608- # Make sure there are enough elements
609- if len (starred_values ) < after_star_count :
610- raise ValueError ("Not enough values to unpack" )
611-
612- # Separate starred values
613- starred_list = starred_values [:- after_star_count ]
614- after_star_values = starred_values [- after_star_count :]
615-
616- # Assign starred target
617- if isinstance (starred_target .value , ast .Name ):
618- self ._set_name_value (
619- starred_target .value .id , starred_list
620- )
621-
622- # Assign elements after starred
623- after_elements = target .elts [star_index + 1 :]
624- for tgt , val in zip (after_elements , after_star_values ):
625- self ._handle_unpacking_target (tgt , val )
626- else :
627- # If no elements after starred, just assign the rest
628- # to the starred target
629- if isinstance (starred_target .value , ast .Name ):
630- self ._set_name_value (
631- starred_target .value .id , starred_values
632- )
633- else :
634- # Standard unpacking without starred expression
635- value_list = list (value )
636- if len (value_list ) < len (target .elts ):
637- raise ValueError ("Not enough values to unpack" )
638- elif len (value_list ) > len (target .elts ):
639- raise ValueError ("Too many values to unpack" )
640-
641- # Unpack each element
642- for tgt , val in zip (target .elts , value ):
643- self ._handle_unpacking_target (tgt , val )
644- except (TypeError , ValueError ) as e :
645- raise UnsupportedUnpackingError (str (e )) from e
700+ self ._handle_sequence_unpacking (target , value )
646701 else :
647702 raise UnsupportedUnpackingError (
648703 f"Unsupported unpacking target type: { type (target ).__name__ } "
0 commit comments