cmd2 2.5.10__py3-none-any.whl → 2.6.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
cmd2/py_bridge.py CHANGED
@@ -1,7 +1,6 @@
1
- # coding=utf-8
2
- """
3
- Bridges calls made inside of a Python environment to the Cmd2 host app
4
- while maintaining a reasonable degree of isolation between the two.
1
+ """Bridges calls made inside of a Python environment to the Cmd2 host app.
2
+
3
+ Maintains a reasonable degree of isolation between the two.
5
4
  """
6
5
 
7
6
  import sys
@@ -13,7 +12,6 @@ from typing import (
13
12
  IO,
14
13
  TYPE_CHECKING,
15
14
  Any,
16
- List,
17
15
  NamedTuple,
18
16
  Optional,
19
17
  TextIO,
@@ -30,7 +28,7 @@ if TYPE_CHECKING: # pragma: no cover
30
28
 
31
29
 
32
30
  class CommandResult(NamedTuple):
33
- """Encapsulates the results from a cmd2 app command
31
+ """Encapsulates the results from a cmd2 app command.
34
32
 
35
33
  :stdout: str - output captured from stdout while this command is executing
36
34
  :stderr: str - output captured from stderr while this command is executing
@@ -71,20 +69,17 @@ class CommandResult(NamedTuple):
71
69
  data: Any = None
72
70
 
73
71
  def __bool__(self) -> bool:
74
- """Returns True if the command succeeded, otherwise False"""
75
-
72
+ """Return True if the command succeeded, otherwise False."""
76
73
  # If data was set, then use it to determine success
77
74
  if self.data is not None:
78
75
  return bool(self.data)
79
76
 
80
77
  # Otherwise check if stderr was filled out
81
- else:
82
- return not self.stderr
78
+ return not self.stderr
83
79
 
84
80
 
85
81
  class PyBridge:
86
- """
87
- Provides a Python API wrapper for application commands.
82
+ """Provides a Python API wrapper for application commands.
88
83
 
89
84
  :param cmd2_app: app being controlled by this PyBridge.
90
85
  :param add_to_history: If True, then add all commands run by this PyBridge to history.
@@ -92,6 +87,7 @@ class PyBridge:
92
87
  """
93
88
 
94
89
  def __init__(self, cmd2_app: 'cmd2.Cmd', *, add_to_history: bool = True) -> None:
90
+ """Initialize PyBridge instances."""
95
91
  self._cmd2_app = cmd2_app
96
92
  self._add_to_history = add_to_history
97
93
  self.cmd_echo = False
@@ -99,15 +95,15 @@ class PyBridge:
99
95
  # Tells if any of the commands run via __call__ returned True for stop
100
96
  self.stop = False
101
97
 
102
- def __dir__(self) -> List[str]:
103
- """Return a custom set of attribute names"""
104
- attributes: List[str] = []
98
+ def __dir__(self) -> list[str]:
99
+ """Return a custom set of attribute names."""
100
+ attributes: list[str] = []
105
101
  attributes.insert(0, 'cmd_echo')
106
102
  return attributes
107
103
 
108
104
  def __call__(self, command: str, *, echo: Optional[bool] = None) -> CommandResult:
109
- """
110
- Provide functionality to call application commands by calling PyBridge
105
+ """Provide functionality to call application commands by calling PyBridge.
106
+
111
107
  ex: app('help')
112
108
  :param command: command line being run
113
109
  :param echo: If provided, this temporarily overrides the value of self.cmd_echo while the
@@ -131,23 +127,21 @@ class PyBridge:
131
127
  stop = False
132
128
  try:
133
129
  self._cmd2_app.stdout = cast(TextIO, copy_cmd_stdout)
134
- with redirect_stdout(cast(IO[str], copy_cmd_stdout)):
135
- with redirect_stderr(cast(IO[str], copy_stderr)):
136
- stop = self._cmd2_app.onecmd_plus_hooks(
137
- command,
138
- add_to_history=self._add_to_history,
139
- py_bridge_call=True,
140
- )
130
+ with redirect_stdout(cast(IO[str], copy_cmd_stdout)), redirect_stderr(cast(IO[str], copy_stderr)):
131
+ stop = self._cmd2_app.onecmd_plus_hooks(
132
+ command,
133
+ add_to_history=self._add_to_history,
134
+ py_bridge_call=True,
135
+ )
141
136
  finally:
142
137
  with self._cmd2_app.sigint_protection:
143
138
  self._cmd2_app.stdout = cast(IO[str], copy_cmd_stdout.inner_stream)
144
139
  self.stop = stop or self.stop
145
140
 
146
141
  # Save the result
147
- result = CommandResult(
142
+ return CommandResult(
148
143
  stdout=copy_cmd_stdout.getvalue(),
149
144
  stderr=copy_stderr.getvalue(),
150
145
  stop=stop,
151
146
  data=self._cmd2_app.last_result,
152
147
  )
153
- return result
cmd2/rl_utils.py CHANGED
@@ -1,15 +1,11 @@
1
- # coding=utf-8
2
- """
3
- Imports the proper Readline for the platform and provides utility functions for it
4
- """
1
+ """Imports the proper Readline for the platform and provides utility functions for it."""
5
2
 
3
+ import contextlib
6
4
  import sys
7
5
  from enum import (
8
6
  Enum,
9
7
  )
10
- from typing import (
11
- Union,
12
- )
8
+ from typing import Union
13
9
 
14
10
  #########################################################################################################################
15
11
  # NOTE ON LIBEDIT:
@@ -32,14 +28,12 @@ try:
32
28
  import gnureadline as readline # type: ignore[import]
33
29
  except ImportError:
34
30
  # Note: If this actually fails, you should install gnureadline on Linux/Mac or pyreadline3 on Windows.
35
- try:
31
+ with contextlib.suppress(ImportError):
36
32
  import readline # type: ignore[no-redef]
37
- except ImportError: # pragma: no cover
38
- pass
39
33
 
40
34
 
41
35
  class RlType(Enum):
42
- """Readline library types we support"""
36
+ """Readline library types we support."""
43
37
 
44
38
  GNU = 1
45
39
  PYREADLINE = 2
@@ -72,30 +66,30 @@ if 'pyreadline3' in sys.modules:
72
66
  if sys.stdout is not None and sys.stdout.isatty(): # pragma: no cover
73
67
 
74
68
  def enable_win_vt100(handle: HANDLE) -> bool:
75
- """
76
- Enables VT100 character sequences in a Windows console
69
+ """Enable VT100 character sequences in a Windows console.
70
+
77
71
  This only works on Windows 10 and up
78
72
  :param handle: the handle on which to enable vt100
79
- :return: True if vt100 characters are enabled for the handle
73
+ :return: True if vt100 characters are enabled for the handle.
80
74
  """
81
- ENABLE_VIRTUAL_TERMINAL_PROCESSING = 0x0004
75
+ enable_virtual_terminal_processing = 0x0004
82
76
 
83
77
  # Get the current mode for this handle in the console
84
78
  cur_mode = DWORD(0)
85
79
  readline.rl.console.GetConsoleMode(handle, byref(cur_mode))
86
80
 
87
- retVal = False
81
+ ret_val = False
88
82
 
89
83
  # Check if ENABLE_VIRTUAL_TERMINAL_PROCESSING is already enabled
90
- if (cur_mode.value & ENABLE_VIRTUAL_TERMINAL_PROCESSING) != 0:
91
- retVal = True
84
+ if (cur_mode.value & enable_virtual_terminal_processing) != 0:
85
+ ret_val = True
92
86
 
93
- elif readline.rl.console.SetConsoleMode(handle, cur_mode.value | ENABLE_VIRTUAL_TERMINAL_PROCESSING):
87
+ elif readline.rl.console.SetConsoleMode(handle, cur_mode.value | enable_virtual_terminal_processing):
94
88
  # Restore the original mode when we exit
95
89
  atexit.register(readline.rl.console.SetConsoleMode, handle, cur_mode)
96
- retVal = True
90
+ ret_val = True
97
91
 
98
- return retVal
92
+ return ret_val
99
93
 
100
94
  # Enable VT100 sequences for stdout and stderr
101
95
  STD_OUT_HANDLE = -11
@@ -107,15 +101,15 @@ if 'pyreadline3' in sys.modules:
107
101
  ############################################################################################################
108
102
  # pyreadline3 is incomplete in terms of the Python readline API. Add the missing functions we need.
109
103
  ############################################################################################################
110
- # readline.remove_history_item()
111
- try:
112
- getattr(readline, 'remove_history_item')
113
- except AttributeError:
104
+ # Add missing `readline.remove_history_item()`
105
+ if not hasattr(readline, 'remove_history_item'):
114
106
 
115
107
  def pyreadline_remove_history_item(pos: int) -> None:
116
- """
117
- An implementation of remove_history_item() for pyreadline3
118
- :param pos: The 0-based position in history to remove
108
+ """Remove the specified item number from the pyreadline3 history.
109
+
110
+ An implementation of remove_history_item() for pyreadline3.
111
+
112
+ :param pos: The 0-based position in history to remove.
119
113
  """
120
114
  # Save of the current location of the history cursor
121
115
  saved_cursor = readline.rl.mode._history.history_cursor
@@ -159,10 +153,9 @@ else:
159
153
 
160
154
 
161
155
  def rl_force_redisplay() -> None: # pragma: no cover
162
- """
163
- Causes readline to display the prompt and input text wherever the cursor is and start
164
- reading input from this location. This is the proper way to restore the input line after
165
- printing to the screen
156
+ """Causes readline to display the prompt and input text wherever the cursor is and start reading input from this location.
157
+
158
+ This is the proper way to restore the input line after printing to the screen.
166
159
  """
167
160
  if not sys.stdout.isatty():
168
161
  return
@@ -181,34 +174,25 @@ def rl_force_redisplay() -> None: # pragma: no cover
181
174
 
182
175
 
183
176
  def rl_get_point() -> int: # pragma: no cover
184
- """
185
- Returns the offset of the current cursor position in rl_line_buffer
186
- """
177
+ """Return the offset of the current cursor position in rl_line_buffer."""
187
178
  if rl_type == RlType.GNU:
188
179
  return ctypes.c_int.in_dll(readline_lib, "rl_point").value
189
180
 
190
- elif rl_type == RlType.PYREADLINE:
181
+ if rl_type == RlType.PYREADLINE:
191
182
  return int(readline.rl.mode.l_buffer.point)
192
183
 
193
- else:
194
- return 0
184
+ return 0
195
185
 
196
186
 
197
187
  def rl_get_prompt() -> str: # pragma: no cover
198
- """Get Readline's prompt"""
188
+ """Get Readline's prompt."""
199
189
  if rl_type == RlType.GNU:
200
190
  encoded_prompt = ctypes.c_char_p.in_dll(readline_lib, "rl_prompt").value
201
- if encoded_prompt is None:
202
- prompt = ''
203
- else:
204
- prompt = encoded_prompt.decode(encoding='utf-8')
191
+ prompt = '' if encoded_prompt is None else encoded_prompt.decode(encoding='utf-8')
205
192
 
206
193
  elif rl_type == RlType.PYREADLINE:
207
194
  prompt_data: Union[str, bytes] = readline.rl.prompt
208
- if isinstance(prompt_data, bytes):
209
- prompt = prompt_data.decode(encoding='utf-8')
210
- else:
211
- prompt = prompt_data
195
+ prompt = prompt_data.decode(encoding='utf-8') if isinstance(prompt_data, bytes) else prompt_data
212
196
 
213
197
  else:
214
198
  prompt = ''
@@ -217,27 +201,22 @@ def rl_get_prompt() -> str: # pragma: no cover
217
201
 
218
202
 
219
203
  def rl_get_display_prompt() -> str: # pragma: no cover
220
- """
221
- Get Readline's currently displayed prompt.
204
+ """Get Readline's currently displayed prompt.
222
205
 
223
206
  In GNU Readline, the displayed prompt sometimes differs from the prompt.
224
207
  This occurs in functions that use the prompt string as a message area, such as incremental search.
225
208
  """
226
209
  if rl_type == RlType.GNU:
227
210
  encoded_prompt = ctypes.c_char_p.in_dll(readline_lib, "rl_display_prompt").value
228
- if encoded_prompt is None:
229
- prompt = ''
230
- else:
231
- prompt = encoded_prompt.decode(encoding='utf-8')
211
+ prompt = '' if encoded_prompt is None else encoded_prompt.decode(encoding='utf-8')
232
212
  return rl_unescape_prompt(prompt)
233
- else:
234
- return rl_get_prompt()
213
+ return rl_get_prompt()
235
214
 
236
215
 
237
216
  def rl_set_prompt(prompt: str) -> None: # pragma: no cover
238
- """
239
- Sets Readline's prompt
240
- :param prompt: the new prompt value
217
+ """Set Readline's prompt.
218
+
219
+ :param prompt: the new prompt value.
241
220
  """
242
221
  escaped_prompt = rl_escape_prompt(prompt)
243
222
 
@@ -250,8 +229,7 @@ def rl_set_prompt(prompt: str) -> None: # pragma: no cover
250
229
 
251
230
 
252
231
  def rl_escape_prompt(prompt: str) -> str:
253
- """
254
- Overcome bug in GNU Readline in relation to calculation of prompt length in presence of ANSI escape codes
232
+ """Overcome bug in GNU Readline in relation to calculation of prompt length in presence of ANSI escape codes.
255
233
 
256
234
  :param prompt: original prompt
257
235
  :return: prompt safe to pass to GNU Readline
@@ -278,12 +256,11 @@ def rl_escape_prompt(prompt: str) -> str:
278
256
 
279
257
  return result
280
258
 
281
- else:
282
- return prompt
259
+ return prompt
283
260
 
284
261
 
285
262
  def rl_unescape_prompt(prompt: str) -> str:
286
- """Remove escape characters from a Readline prompt"""
263
+ """Remove escape characters from a Readline prompt."""
287
264
  if rl_type == RlType.GNU:
288
265
  escape_start = "\x01"
289
266
  escape_end = "\x02"
@@ -293,16 +270,16 @@ def rl_unescape_prompt(prompt: str) -> str:
293
270
 
294
271
 
295
272
  def rl_in_search_mode() -> bool: # pragma: no cover
296
- """Check if readline is doing either an incremental (e.g. Ctrl-r) or non-incremental (e.g. Esc-p) search"""
273
+ """Check if readline is doing either an incremental (e.g. Ctrl-r) or non-incremental (e.g. Esc-p) search."""
297
274
  if rl_type == RlType.GNU:
298
275
  # GNU Readline defines constants that we can use to determine if in search mode.
299
276
  # RL_STATE_ISEARCH 0x0000080
300
277
  # RL_STATE_NSEARCH 0x0000100
301
- IN_SEARCH_MODE = 0x0000180
278
+ in_search_mode = 0x0000180
302
279
 
303
280
  readline_state = ctypes.c_int.in_dll(readline_lib, "rl_readline_state").value
304
- return bool(IN_SEARCH_MODE & readline_state)
305
- elif rl_type == RlType.PYREADLINE:
281
+ return bool(in_search_mode & readline_state)
282
+ if rl_type == RlType.PYREADLINE:
306
283
  from pyreadline3.modes.emacs import ( # type: ignore[import]
307
284
  EmacsMode,
308
285
  )
@@ -317,5 +294,4 @@ def rl_in_search_mode() -> bool: # pragma: no cover
317
294
  readline.rl.mode._process_non_incremental_search_keyevent,
318
295
  )
319
296
  return readline.rl.mode.process_keyevent_queue[-1] in search_funcs
320
- else:
321
- return False
297
+ return False