Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/IPython/core/splitinput.py: 43%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

46 statements  

1""" 

2Simple utility for splitting user input. This is used by both inputsplitter and 

3prefilter. 

4""" 

5 

6# ----------------------------------------------------------------------------- 

7# Imports 

8# ----------------------------------------------------------------------------- 

9 

10import re 

11import warnings 

12 

13from IPython.core.oinspect import OInfo 

14 

15# ----------------------------------------------------------------------------- 

16# Main function 

17# ----------------------------------------------------------------------------- 

18 

19# RegExp for splitting line contents into pre-char//first word-method//rest. 

20# For clarity, each group in on one line. 

21 

22# WARNING: update the regexp if the escapes in interactiveshell are changed, as 

23# they are hardwired in. 

24 

25# Although it's not solely driven by the regex, note that: 

26# ,;/% only trigger if they are the first character on the line 

27# ! and !! trigger if they are first char(s) *or* follow an indent 

28# ? triggers as first or last char. 

29 

30line_split = re.compile( 

31 r""" 

32 ^(\s*) # any leading space 

33 ([,;/%]|!!?|\?\??)? # escape character or characters 

34 \s*(%{0,2}[\w\.\*]*) # function/method, possibly with leading % 

35 # to correctly treat things like '?%magic' 

36 (.*?$|$) # rest of line 

37 """, 

38 re.VERBOSE, 

39) 

40 

41 

42def split_user_input( 

43 line: str, pattern: re.Pattern[str] | None = None 

44) -> tuple[str, str, str, str]: 

45 """Split user input into initial whitespace, escape character, function part 

46 and the rest. 

47 """ 

48 assert isinstance(line, str) 

49 

50 if pattern is None: 

51 pattern = line_split 

52 match = pattern.match(line) 

53 if not match: 

54 # print("match failed for line '%s'" % line) 

55 try: 

56 ifun, the_rest = line.split(None, 1) 

57 except ValueError: 

58 # print("split failed for line '%s'" % line) 

59 ifun, the_rest = line, "" 

60 pre = re.match(r"^(\s*)(.*)", line).groups()[0] 

61 esc = "" 

62 else: 

63 pre, esc, ifun, the_rest = match.groups() 

64 

65 # print('line:<%s>' % line) # dbg 

66 # print('pre <%s> ifun <%s> rest <%s>' % (pre,ifun.strip(),the_rest)) # dbg 

67 return pre, esc or "", ifun.strip(), the_rest 

68 

69 

70class LineInfo: 

71 """A single line of input and associated info. 

72 

73 Includes the following as properties: 

74 

75 line 

76 The original, raw line 

77 

78 continue_prompt 

79 Is this line a continuation in a sequence of multiline input? 

80 

81 pre 

82 Any leading whitespace. 

83 

84 esc 

85 The escape character(s) in pre or the empty string if there isn't one. 

86 Note that '!!' and '??' are possible values for esc. Otherwise it will 

87 always be a single character. 

88 

89 ifun 

90 The 'function part', which is basically the maximal initial sequence 

91 of valid python identifiers and the '.' character. This is what is 

92 checked for alias and magic transformations, used for auto-calling, 

93 etc. In contrast to Python identifiers, it may start with "%" and contain 

94 "*". 

95 

96 the_rest 

97 Everything else on the line. 

98 

99 raw_the_rest 

100 the_rest without whitespace stripped. 

101 """ 

102 

103 line: str 

104 continue_prompt: bool 

105 pre: str 

106 esc: str 

107 ifun: str 

108 raw_the_rest: str 

109 the_rest: str 

110 pre_char: str 

111 pre_whitespace: str 

112 

113 def __init__(self, line: str, continue_prompt: bool = False) -> None: 

114 assert isinstance(line, str) 

115 self.line = line 

116 self.continue_prompt = continue_prompt 

117 self.pre, self.esc, self.ifun, self.raw_the_rest = split_user_input(line) 

118 self.the_rest = self.raw_the_rest.lstrip() 

119 

120 self.pre_char = self.pre.strip() 

121 if self.pre_char: 

122 self.pre_whitespace = "" # No whitespace allowed before esc chars 

123 else: 

124 self.pre_whitespace = self.pre 

125 

126 def ofind(self, ip) -> OInfo: 

127 """Do a full, attribute-walking lookup of the ifun in the various 

128 namespaces for the given IPython InteractiveShell instance. 

129 

130 Return a dict with keys: {found, obj, ospace, ismagic} 

131 

132 Note: can cause state changes because of calling getattr, but should 

133 only be run if autocall is on and if the line hasn't matched any 

134 other, less dangerous handlers. 

135 

136 Does cache the results of the call, so can be called multiple times 

137 without worrying about *further* damaging state. 

138 

139 .. deprecated:: 9.9 

140 Use ``shell._ofind(line_info.ifun)`` directly instead. 

141 """ 

142 warnings.warn( 

143 "LineInfo.ofind() is deprecated since IPython 9.9. " 

144 "Use shell._ofind(line_info.ifun) directly instead.", 

145 DeprecationWarning, 

146 stacklevel=2, 

147 ) 

148 return ip._ofind(self.ifun) 

149 

150 def __str__(self) -> str: 

151 return "LineInfo [{}|{}|{}|{}]".format(self.pre, self.esc, self.ifun, self.the_rest) 

152 

153 def __repr__(self) -> str: 

154 return "<" + str(self) + ">"