##// END OF EJS Templates
Simplify tokenizing code for VerboseTB.
Thomas Kluyver -
Show More
@@ -832,47 +832,6 b' class VerboseTB(TBTools):'
832 # disabled.
832 # disabled.
833 call = tpl_call_fail % func
833 call = tpl_call_fail % func
834
834
835 # Initialize a list of names on the current line, which the
836 # tokenizer below will populate.
837 names = []
838
839 def tokeneater(token_type, token, start, end, line):
840 """Stateful tokeneater which builds dotted names.
841
842 The list of names it appends to (from the enclosing scope) can
843 contain repeated composite names. This is unavoidable, since
844 there is no way to disambguate partial dotted structures until
845 the full list is known. The caller is responsible for pruning
846 the final list of duplicates before using it."""
847
848 # build composite names
849 if token == '.':
850 try:
851 names[-1] += '.'
852 # store state so the next token is added for x.y.z names
853 tokeneater.name_cont = True
854 return
855 except IndexError:
856 pass
857 if token_type == tokenize.NAME and token not in keyword.kwlist:
858 if tokeneater.name_cont:
859 # Dotted names
860 names[-1] += token
861 tokeneater.name_cont = False
862 else:
863 # Regular new names. We append everything, the caller
864 # will be responsible for pruning the list later. It's
865 # very tricky to try to prune as we go, b/c composite
866 # names can fool us. The pruning at the end is easy
867 # to do (or the caller can print a list with repeated
868 # names if so desired.
869 names.append(token)
870 elif token_type == tokenize.NEWLINE:
871 raise IndexError
872 # we need to store a bit of state in the tokenizer to build
873 # dotted names
874 tokeneater.name_cont = False
875
876 def linereader(file=file, lnum=[lnum], getline=linecache.getline):
835 def linereader(file=file, lnum=[lnum], getline=linecache.getline):
877 if file.endswith(('.pyc','.pyo')):
836 if file.endswith(('.pyc','.pyo')):
878 file = pyfile.source_from_cache(file)
837 file = pyfile.source_from_cache(file)
@@ -883,10 +842,32 b' class VerboseTB(TBTools):'
883 # Build the list of names on this line of code where the exception
842 # Build the list of names on this line of code where the exception
884 # occurred.
843 # occurred.
885 try:
844 try:
886 # This builds the names list in-place by capturing it from the
845 names = []
887 # enclosing scope.
846 name_cont = False
888 for token in generate_tokens(linereader):
847
889 tokeneater(*token)
848 for token_type, token, start, end, line in generate_tokens(linereader):
849 # build composite names
850 if token_type == tokenize.NAME and token not in keyword.kwlist:
851 if name_cont:
852 # Continuation of a dotted name
853 try:
854 names[-1].append(token)
855 except IndexError:
856 names.append([token])
857 name_cont = False
858 else:
859 # Regular new names. We append everything, the caller
860 # will be responsible for pruning the list later. It's
861 # very tricky to try to prune as we go, b/c composite
862 # names can fool us. The pruning at the end is easy
863 # to do (or the caller can print a list with repeated
864 # names if so desired.
865 names.append([token])
866 elif token == '.':
867 name_cont = True
868 elif token_type == tokenize.NEWLINE:
869 break
870
890 except (IndexError, UnicodeDecodeError):
871 except (IndexError, UnicodeDecodeError):
891 # signals exit of tokenizer
872 # signals exit of tokenizer
892 pass
873 pass
@@ -896,6 +877,8 b' class VerboseTB(TBTools):'
896 "The error message is: %s\n" % msg)
877 "The error message is: %s\n" % msg)
897 error(_m)
878 error(_m)
898
879
880 # Join composite names (e.g. "dict.fromkeys")
881 names = ['.'.join(n) for n in names]
899 # prune names list of duplicates, but keep the right order
882 # prune names list of duplicates, but keep the right order
900 unique_names = uniq_stable(names)
883 unique_names = uniq_stable(names)
901
884
General Comments 0
You need to be logged in to leave comments. Login now