MCPcopy Index your code
hub / github.com/python/cpython / _PasswordLineEditor

Class _PasswordLineEditor

Lib/getpass.py:252–409  ·  view source on GitHub ↗

Handles line editing for password input with echo character.

Source from the content-addressed store, hash-verified

250
251
252class _PasswordLineEditor:
253 """Handles line editing for password input with echo character."""
254
255 def __init__(self, stream, echo_char, ctrl_chars, prompt=""):
256 self.stream = stream
257 self.echo_char = echo_char
258 self.prompt = prompt
259 self.password = []
260 self.cursor_pos = 0
261 self.eof_pressed = False
262 self.literal_next = False
263 self.ctrl = ctrl_chars
264 self.dispatch = {
265 ctrl_chars['SOH']: self.handle_move_start, # Ctrl+A
266 ctrl_chars['ENQ']: self.handle_move_end, # Ctrl+E
267 ctrl_chars['VT']: self.handle_kill_forward, # Ctrl+K
268 ctrl_chars['KILL']: self.handle_kill_line, # Ctrl+U
269 ctrl_chars['WERASE']: self.handle_erase_word, # Ctrl+W
270 ctrl_chars['ERASE']: self.handle_erase, # DEL
271 ctrl_chars['BS']: self.handle_erase, # Backspace
272 # special characters
273 ctrl_chars['LNEXT']: self.handle_literal_next, # Ctrl+V
274 ctrl_chars['EOF']: self.handle_eof, # Ctrl+D
275 ctrl_chars['INTR']: self.handle_interrupt, # Ctrl+C
276 '\x00': self.handle_nop, # ignore NUL
277 }
278
279 def refresh_display(self, prev_len=None):
280 """Redraw the entire password line with *echo_char*.
281
282 If *prev_len* is not specified, the current password length is used.
283 """
284 prompt_len = len(self.prompt)
285 clear_len = prev_len if prev_len is not None else len(self.password)
286 # Clear the entire line (prompt + password) and rewrite.
287 self.stream.write('\r' + ' ' * (prompt_len + clear_len) + '\r')
288 self.stream.write(self.prompt + self.echo_char * len(self.password))
289 if self.cursor_pos < len(self.password):
290 self.stream.write('\b' * (len(self.password) - self.cursor_pos))
291 self.stream.flush()
292
293 def insert_char(self, char):
294 """Insert *char* at cursor position."""
295 self.password.insert(self.cursor_pos, char)
296 self.cursor_pos += 1
297 # Only refresh if inserting in middle.
298 if self.cursor_pos < len(self.password):
299 self.refresh_display()
300 else:
301 self.stream.write(self.echo_char)
302 self.stream.flush()
303
304 def is_eol(self, char):
305 """Check if *char* is a line terminator."""
306 return char in ('\r', '\n')
307
308 def is_eof(self, char):
309 """Check if *char* is a file terminator."""

Callers 1

_readline_with_echo_charFunction · 0.85

Calls

no outgoing calls

Tested by

no test coverage detected

Used in the wild real call sites across dependent graphs

searching dependent graphs…