22 class TextIO(io.TextIOWrapper):
23 """Text wrapper to capture stdout"""
30 errors: Optional[str] = ...,
31 newline: Optional[str] = ...,
32 line_buffering: bool = ...,
33 write_through: bool = ...,
35 super(ProgressBar.TextIO, self).__init__(buffer, encoding, errors, newline, line_buffering, write_through)
38 def write(self, s) -> None:
39 self.func(s.strip("\n "))
41 def get_original(self) -> io.TextIOWrapper:
42 """Get the original Text Wrapper
45 io.TextIOWrapper: Original TextIOWrapper
49 def __init__(self, maxcount: int, prefix: str):
50 """Create a new progress bar
53 maxcount (int): The target counter value
54 prefix (str): The string to prefix the bar with
56 self.maxcount = maxcount
57 self.stdout = sys.stdout
59 self.wrapper = ProgressBar.TextIO(
65 sys.stdout.line_buffering,
66 sys.stdout.write_through,
68 self.printer = threading.Thread(target=self._print_thread)
70 def rename(self, prefix: str) -> None:
71 """Change the prefix of the progress bar
74 prefix (str): The string to prefix the bar with
76 mx_sz = len(self.formatStr.format(prefix, " " * self.bar_len, 100.0, "%"))
77 self.bar_len = min(int(os.get_terminal_size().columns - 1 - (mx_sz / 1.25)), mx_sz)
78 self.bar_len = self.bar_len if self.bar_len > 0 else 0
81 def reset(self, maxcount: int = None, prefix: str = None) -> None:
82 """Reset the progress bar
85 maxcount (int): New target counter value. Defaults to current maxcount.
86 prefix (str): New string to prefix the bar with. Defaults to current prefix.
88 self.maxcount = maxcount or self.maxcount
94 def _new_line(self, line: str) -> None:
95 """The TextIO line handler
98 line (str): line to consume
102 def _progress(self, count, total, prefix="", printString: str = ""):
104 count = min(count, total)
105 filled_len = int(round(self.bar_len * count / float(total)))
107 percents = round(100.0 * count / float(total), 1)
108 bar_prog = "█" * filled_len + "░" * (self.bar_len - filled_len)
110 pro_str = self.formatStr.format(prefix, bar_prog, percents, "%")
111 if len(printString) > 0:
112 self.stdout.write(" " * (os.get_terminal_size().columns - 1))
113 self.stdout.write("\033[F")
114 printString = printString.strip(" \n")
115 spacer = " " * (os.get_terminal_size().columns - 1 - len(printString))
116 self.stdout.write(f"{printString}{spacer}"[: os.get_terminal_size().columns - 1])
117 self.stdout.write("\n")
118 self.stdout.write(pro_str)
121 def _print_thread(self):
122 while self.run or len(self.Lines) > 0:
126 if len(self.Lines) > 0:
127 self._progress(count, self.maxcount, self.prefix, self.Lines.pop())
129 self._progress(count, self.maxcount, self.prefix)
132 def start(self) -> None:
133 """Enable this progress ba
r"""
134 sys.stdout = self.wrapper
138 """Increment the progress ba
r"""
143 """Disable the progress bar, setting it to 100%"""
146 self._progress(self.maxcount, self.maxcount, self.prefix)
148 sys.stdout = self.wrapper.get_original()