3535import time
3636import traceback
3737from abc import abstractmethod
38+ from dataclasses import dataclass
3839from itertools import takewhile
3940from pathlib import Path
4041from types import ModuleType , TracebackType
@@ -380,6 +381,17 @@ class SourceNotFound(Exception):
380381 """Exception raised when the requested source could not be found."""
381382
382383
384+ @dataclass
385+ class _FuncExpr :
386+ """Stack element in Repl._funcname_and_argnum"""
387+
388+ full_expr : str
389+ function_expr : str
390+ arg_number : int
391+ opening : str
392+ keyword : Optional [str ] = None
393+
394+
383395class Repl :
384396 """Implements the necessary guff for a Python-repl-alike interface
385397
@@ -564,37 +576,37 @@ def get_object(self, name):
564576 return obj
565577
566578 @classmethod
567- def _funcname_and_argnum (cls , line ):
579+ def _funcname_and_argnum (
580+ cls , line : str
581+ ) -> Tuple [Optional [str ], Optional [Union [str , int ]]]:
568582 """Parse out the current function name and arg from a line of code."""
569- # each list in stack:
570- # [full_expr, function_expr, arg_number, opening]
571- # arg_number may be a string if we've encountered a keyword
572- # argument so we're done counting
573- stack = [["" , "" , 0 , "" ]]
583+ # each element in stack is a _FuncExpr instance
584+ # if keyword is not None, we've encountered a keyword and so we're done counting
585+ stack = [_FuncExpr ("" , "" , 0 , "" )]
574586 try :
575587 for (token , value ) in Python3Lexer ().get_tokens (line ):
576588 if token is Token .Punctuation :
577589 if value in "([{" :
578- stack .append ([ "" , "" , 0 , value ] )
590+ stack .append (_FuncExpr ( "" , "" , 0 , value ) )
579591 elif value in ")]}" :
580- full , _ , _ , start = stack .pop ()
581- expr = start + full + value
582- stack [- 1 ][ 1 ] += expr
583- stack [- 1 ][ 0 ] += expr
592+ element = stack .pop ()
593+ expr = element . opening + element . full_expr + value
594+ stack [- 1 ]. function_expr += expr
595+ stack [- 1 ]. full_expr += expr
584596 elif value == "," :
585- try :
586- stack [- 1 ][ 2 ] += 1
587- except TypeError :
588- stack [- 1 ][ 2 ] = ""
589- stack [- 1 ][ 1 ] = ""
590- stack [- 1 ][ 0 ] += value
591- elif value == ":" and stack [- 1 ][ 3 ] == "lambda" :
592- expr = stack .pop ()[ 0 ] + ":"
593- stack [- 1 ][ 1 ] += expr
594- stack [- 1 ][ 0 ] += expr
597+ if stack [ - 1 ]. keyword is None :
598+ stack [- 1 ]. arg_number += 1
599+ else :
600+ stack [- 1 ]. keyword = ""
601+ stack [- 1 ]. function_expr = ""
602+ stack [- 1 ]. full_expr += value
603+ elif value == ":" and stack [- 1 ]. opening == "lambda" :
604+ expr = stack .pop (). full_expr + ":"
605+ stack [- 1 ]. function_expr += expr
606+ stack [- 1 ]. full_expr += expr
595607 else :
596- stack [- 1 ][ 1 ] = ""
597- stack [- 1 ][ 0 ] += value
608+ stack [- 1 ]. function_expr = ""
609+ stack [- 1 ]. full_expr += value
598610 elif (
599611 token is Token .Number
600612 or token in Token .Number .subtypes
@@ -603,25 +615,25 @@ def _funcname_and_argnum(cls, line):
603615 or token is Token .Operator
604616 and value == "."
605617 ):
606- stack [- 1 ][ 1 ] += value
607- stack [- 1 ][ 0 ] += value
618+ stack [- 1 ]. function_expr += value
619+ stack [- 1 ]. full_expr += value
608620 elif token is Token .Operator and value == "=" :
609- stack [- 1 ][ 2 ] = stack [- 1 ][ 1 ]
610- stack [- 1 ][ 1 ] = ""
611- stack [- 1 ][ 0 ] += value
621+ stack [- 1 ]. keyword = stack [- 1 ]. function_expr
622+ stack [- 1 ]. function_expr = ""
623+ stack [- 1 ]. full_expr += value
612624 elif token is Token .Number or token in Token .Number .subtypes :
613- stack [- 1 ][ 1 ] = value
614- stack [- 1 ][ 0 ] += value
625+ stack [- 1 ]. function_expr = value
626+ stack [- 1 ]. full_expr += value
615627 elif token is Token .Keyword and value == "lambda" :
616- stack .append ([ value , "" , 0 , value ] )
628+ stack .append (_FuncExpr ( value , "" , 0 , value ) )
617629 else :
618- stack [- 1 ][ 1 ] = ""
619- stack [- 1 ][ 0 ] += value
620- while stack [- 1 ][ 3 ] in "[{" :
630+ stack [- 1 ]. function_expr = ""
631+ stack [- 1 ]. full_expr += value
632+ while stack [- 1 ]. opening in "[{" :
621633 stack .pop ()
622- _ , _ , arg_number , _ = stack .pop ()
623- _ , func , _ , _ = stack .pop ()
624- return func , arg_number
634+ elem1 = stack .pop ()
635+ elem2 = stack .pop ()
636+ return elem2 . function_expr , elem1 . keyword or elem1 . arg_number
625637 except IndexError :
626638 return None , None
627639
0 commit comments