Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/prompt_toolkit/input/base.py: 75%

57 statements  

« prev     ^ index     » next       coverage.py v7.4.4, created at 2024-04-20 06:09 +0000

1""" 

2Abstraction of CLI Input. 

3""" 

4from __future__ import annotations 

5 

6from abc import ABCMeta, abstractmethod, abstractproperty 

7from contextlib import contextmanager 

8from typing import Callable, ContextManager, Generator 

9 

10from prompt_toolkit.key_binding import KeyPress 

11 

12__all__ = [ 

13 "Input", 

14 "PipeInput", 

15 "DummyInput", 

16] 

17 

18 

19class Input(metaclass=ABCMeta): 

20 """ 

21 Abstraction for any input. 

22 

23 An instance of this class can be given to the constructor of a 

24 :class:`~prompt_toolkit.application.Application` and will also be 

25 passed to the :class:`~prompt_toolkit.eventloop.base.EventLoop`. 

26 """ 

27 

28 @abstractmethod 

29 def fileno(self) -> int: 

30 """ 

31 Fileno for putting this in an event loop. 

32 """ 

33 

34 @abstractmethod 

35 def typeahead_hash(self) -> str: 

36 """ 

37 Identifier for storing type ahead key presses. 

38 """ 

39 

40 @abstractmethod 

41 def read_keys(self) -> list[KeyPress]: 

42 """ 

43 Return a list of Key objects which are read/parsed from the input. 

44 """ 

45 

46 def flush_keys(self) -> list[KeyPress]: 

47 """ 

48 Flush the underlying parser. and return the pending keys. 

49 (Used for vt100 input.) 

50 """ 

51 return [] 

52 

53 def flush(self) -> None: 

54 "The event loop can call this when the input has to be flushed." 

55 pass 

56 

57 @abstractproperty 

58 def closed(self) -> bool: 

59 "Should be true when the input stream is closed." 

60 return False 

61 

62 @abstractmethod 

63 def raw_mode(self) -> ContextManager[None]: 

64 """ 

65 Context manager that turns the input into raw mode. 

66 """ 

67 

68 @abstractmethod 

69 def cooked_mode(self) -> ContextManager[None]: 

70 """ 

71 Context manager that turns the input into cooked mode. 

72 """ 

73 

74 @abstractmethod 

75 def attach(self, input_ready_callback: Callable[[], None]) -> ContextManager[None]: 

76 """ 

77 Return a context manager that makes this input active in the current 

78 event loop. 

79 """ 

80 

81 @abstractmethod 

82 def detach(self) -> ContextManager[None]: 

83 """ 

84 Return a context manager that makes sure that this input is not active 

85 in the current event loop. 

86 """ 

87 

88 def close(self) -> None: 

89 "Close input." 

90 pass 

91 

92 

93class PipeInput(Input): 

94 """ 

95 Abstraction for pipe input. 

96 """ 

97 

98 @abstractmethod 

99 def send_bytes(self, data: bytes) -> None: 

100 """Feed byte string into the pipe""" 

101 

102 @abstractmethod 

103 def send_text(self, data: str) -> None: 

104 """Feed a text string into the pipe""" 

105 

106 

107class DummyInput(Input): 

108 """ 

109 Input for use in a `DummyApplication` 

110 

111 If used in an actual application, it will make the application render 

112 itself once and exit immediately, due to an `EOFError`. 

113 """ 

114 

115 def fileno(self) -> int: 

116 raise NotImplementedError 

117 

118 def typeahead_hash(self) -> str: 

119 return "dummy-%s" % id(self) 

120 

121 def read_keys(self) -> list[KeyPress]: 

122 return [] 

123 

124 @property 

125 def closed(self) -> bool: 

126 # This needs to be true, so that the dummy input will trigger an 

127 # `EOFError` immediately in the application. 

128 return True 

129 

130 def raw_mode(self) -> ContextManager[None]: 

131 return _dummy_context_manager() 

132 

133 def cooked_mode(self) -> ContextManager[None]: 

134 return _dummy_context_manager() 

135 

136 def attach(self, input_ready_callback: Callable[[], None]) -> ContextManager[None]: 

137 # Call the callback immediately once after attaching. 

138 # This tells the callback to call `read_keys` and check the 

139 # `input.closed` flag, after which it won't receive any keys, but knows 

140 # that `EOFError` should be raised. This unblocks `read_from_input` in 

141 # `application.py`. 

142 input_ready_callback() 

143 

144 return _dummy_context_manager() 

145 

146 def detach(self) -> ContextManager[None]: 

147 return _dummy_context_manager() 

148 

149 

150@contextmanager 

151def _dummy_context_manager() -> Generator[None, None, None]: 

152 yield