35
35
import time
36
36
import traceback
37
37
from abc import abstractmethod
38
+ from dataclasses import dataclass
38
39
from itertools import takewhile
39
40
from pathlib import Path
40
41
from types import ModuleType , TracebackType
@@ -380,6 +381,17 @@ class SourceNotFound(Exception):
380
381
"""Exception raised when the requested source could not be found."""
381
382
382
383
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
+
383
395
class Repl :
384
396
"""Implements the necessary guff for a Python-repl-alike interface
385
397
@@ -564,37 +576,37 @@ def get_object(self, name):
564
576
return obj
565
577
566
578
@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 ]]]:
568
582
"""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 , "" )]
574
586
try :
575
587
for (token , value ) in Python3Lexer ().get_tokens (line ):
576
588
if token is Token .Punctuation :
577
589
if value in "([{" :
578
- stack .append ([ "" , "" , 0 , value ] )
590
+ stack .append (_FuncExpr ( "" , "" , 0 , value ) )
579
591
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
584
596
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
595
607
else :
596
- stack [- 1 ][ 1 ] = ""
597
- stack [- 1 ][ 0 ] += value
608
+ stack [- 1 ]. function_expr = ""
609
+ stack [- 1 ]. full_expr += value
598
610
elif (
599
611
token is Token .Number
600
612
or token in Token .Number .subtypes
@@ -603,25 +615,25 @@ def _funcname_and_argnum(cls, line):
603
615
or token is Token .Operator
604
616
and value == "."
605
617
):
606
- stack [- 1 ][ 1 ] += value
607
- stack [- 1 ][ 0 ] += value
618
+ stack [- 1 ]. function_expr += value
619
+ stack [- 1 ]. full_expr += value
608
620
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
612
624
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
615
627
elif token is Token .Keyword and value == "lambda" :
616
- stack .append ([ value , "" , 0 , value ] )
628
+ stack .append (_FuncExpr ( value , "" , 0 , value ) )
617
629
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 "[{" :
621
633
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
625
637
except IndexError :
626
638
return None , None
627
639
0 commit comments