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

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

47 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 sys 

12import warnings 

13 

14from IPython.core.oinspect import OInfo 

15 

16# ----------------------------------------------------------------------------- 

17# Main function 

18# ----------------------------------------------------------------------------- 

19 

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

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

22 

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

24# they are hardwired in. 

25 

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

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

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

29# ? triggers as first or last char. 

30 

31line_split = re.compile( 

32 r""" 

33 ^(\s*) # any leading space 

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

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

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

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

38 """, 

39 re.VERBOSE, 

40) 

41 

42 

43def split_user_input( 

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

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

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

47 and the rest. 

48 """ 

49 assert isinstance(line, str) 

50 

51 if pattern is None: 

52 pattern = line_split 

53 match = pattern.match(line) 

54 if not match: 

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

56 try: 

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

58 except ValueError: 

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

60 ifun, the_rest = line, "" 

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

62 esc = "" 

63 else: 

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

65 

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

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

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

69 

70 

71class LineInfo: 

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

73 

74 Includes the following as properties: 

75 

76 line 

77 The original, raw line 

78 

79 continue_prompt 

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

81 

82 pre 

83 Any leading whitespace. 

84 

85 esc 

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

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

88 always be a single character. 

89 

90 ifun 

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

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

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

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

95 "*". 

96 

97 the_rest 

98 Everything else on the line. 

99 

100 raw_the_rest 

101 the_rest without whitespace stripped. 

102 """ 

103 

104 line: str 

105 continue_prompt: bool 

106 pre: str 

107 esc: str 

108 ifun: str 

109 raw_the_rest: str 

110 the_rest: str 

111 pre_char: str 

112 pre_whitespace: str 

113 

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

115 assert isinstance(line, str) 

116 self.line = line 

117 self.continue_prompt = continue_prompt 

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

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

120 

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

122 if self.pre_char: 

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

124 else: 

125 self.pre_whitespace = self.pre 

126 

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

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

129 namespaces for the given IPython InteractiveShell instance. 

130 

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

132 

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

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

135 other, less dangerous handlers. 

136 

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

138 without worrying about *further* damaging state. 

139 

140 .. deprecated:: 9.8 

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

142 """ 

143 warnings.warn( 

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

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

146 DeprecationWarning, 

147 stacklevel=2, 

148 ) 

149 return ip._ofind(self.ifun) 

150 

151 def __str__(self) -> str: 

152 return "LineInfo [%s|%s|%s|%s]" % (self.pre, self.esc, self.ifun, self.the_rest) 

153 

154 def __repr__(self) -> str: 

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