pocketutils.tools.console_tools   A
last analyzed

Complexity

Total Complexity 10

Size/Duplication

Total Lines 80
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 10
eloc 39
dl 0
loc 80
rs 10
c 0
b 0
f 0

3 Methods

Rating   Name   Duplication   Size   Complexity  
A ConsoleUtils.clear_line() 0 12 2
A ConsoleUtils.prompt_yes_no() 0 14 4
A ConsoleUtils.confirm() 0 25 4
1
# SPDX-FileCopyrightText: Copyright 2020-2023, Contributors to pocketutils
2
# SPDX-PackageHomePage: https://github.com/dmyersturnbull/pocketutils
3
# SPDX-License-Identifier: Apache-2.0
4
"""
5
6
"""
7
8
import logging
9
import sys
10
from collections.abc import Callable
11
from dataclasses import dataclass
12
from typing import Any, ClassVar, Self
13
14
logger = logging.getLogger("pocketutils")
15
16
__all__ = ["ConsoleUtils", "ConsoleTools"]
17
18
19
@dataclass(slots=True, frozen=True)
20
class ConsoleUtils:
21
    CURSOR_UP_ONE: ClassVar[str] = "\x1b[1A"
22
    ERASE_LINE: ClassVar[str] = "\x1b[2K"
23
24
    def prompt_yes_no(self: Self, msg: str, writer: Callable[[str], Any] = sys.stdout.write) -> bool:
25
        """
26
        Asks for "yes" or "no" via `input`.
27
        Consider using `typer.prompt` instead.
28
        """
29
        while True:
30
            writer(msg + " ")
31
            command = input("")
32
            if command.lower() == "yes":
33
                return True
34
            elif command.lower() == "no":
35
                return False
36
            else:
37
                writer("Enter 'yes' or 'no'.\n")
38
39
    def confirm(
40
        self: Self,
41
        msg: str = "Confirm? [yes/no]",
42
        *,
43
        input_fn: Callable[[str], str] = input,
44
        writer: Callable[[str], Any] = sys.stdout.write,
45
    ) -> bool:
46
        """
47
        Asks for a confirmation from the user using the builtin `input`.
48
49
        Consider using `typer.prompt` instead.
50
            msg: If None, no message is written
51
            input_fn: Function to get the user input (its argument is always '')
52
            writer: Print using this function (should not print a newline by default)
53
54
        Returns:
55
            True if the user answered 'yes'; False otherwise
56
        """
57
        while True:
58
            writer(msg + " ")
59
            command = input_fn("").lower()
60
            if command in ["yes", "y"]:
61
                return True
62
            elif command in ["no", "n"]:
63
                return False
64
65
    def clear_line(self: Self, n: int = 1, writer: Callable[[str], None] = sys.stdout.write) -> None:
66
        """
67
        Writes control characters to stdout to delete the previous line and move the cursor up.
68
        This only works in a shell.
69
70
        Args:
71
            n: The number of lines to erase
72
            writer: Function to call (passing the string)
73
        """
74
        for _ in range(n):
75
            writer(ConsoleTools.CURSOR_UP_ONE)
76
            writer(ConsoleTools.ERASE_LINE)
77
78
79
ConsoleTools = ConsoleUtils()
80