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

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

48 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 

12from typing import TYPE_CHECKING 

13 

14if TYPE_CHECKING: 

15 from IPython.core.oinspect import OInfo 

16 

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

18# Main function 

19# ----------------------------------------------------------------------------- 

20 

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

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

23 

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

25# they are hardwired in. 

26 

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

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

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

30# ? triggers as first or last char. 

31 

32line_split = re.compile( 

33 r""" 

34 ^(\s*) # any leading space 

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

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

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

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

39 """, 

40 re.VERBOSE, 

41) 

42 

43 

44def split_user_input( 

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

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

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

48 and the rest. 

49 """ 

50 assert isinstance(line, str) 

51 

52 if pattern is None: 

53 pattern = line_split 

54 match = pattern.match(line) 

55 if not match: 

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

57 try: 

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

59 except ValueError: 

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

61 ifun, the_rest = line, "" 

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

63 esc = "" 

64 else: 

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

66 

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

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

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

70 

71 

72class LineInfo: 

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

74 

75 Includes the following as properties: 

76 

77 line 

78 The original, raw line 

79 

80 continue_prompt 

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

82 

83 pre 

84 Any leading whitespace. 

85 

86 esc 

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

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

89 always be a single character. 

90 

91 ifun 

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

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

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

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

96 "*". 

97 

98 the_rest 

99 Everything else on the line. 

100 

101 raw_the_rest 

102 the_rest without whitespace stripped. 

103 """ 

104 

105 line: str 

106 continue_prompt: bool 

107 pre: str 

108 esc: str 

109 ifun: str 

110 raw_the_rest: str 

111 the_rest: str 

112 pre_char: str 

113 pre_whitespace: str 

114 

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

116 assert isinstance(line, str) 

117 self.line = line 

118 self.continue_prompt = continue_prompt 

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

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

121 

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

123 if self.pre_char: 

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

125 else: 

126 self.pre_whitespace = self.pre 

127 

128 def ofind(self, ip) -> "OInfo": 

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

130 namespaces for the given IPython InteractiveShell instance. 

131 

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

133 

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

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

136 other, less dangerous handlers. 

137 

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

139 without worrying about *further* damaging state. 

140 

141 .. deprecated:: 9.9 

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

143 """ 

144 warnings.warn( 

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

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

147 DeprecationWarning, 

148 stacklevel=2, 

149 ) 

150 return ip._ofind(self.ifun) 

151 

152 def __str__(self) -> str: 

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

154 

155 def __repr__(self) -> str: 

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