-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcoh_progress_bar.py
143 lines (117 loc) · 4.5 KB
/
coh_progress_bar.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
"""Class for creating a tkinter-based progress bar in an external window."""
import tkinter
from tkinter import ttk
class ProgressBar:
"""Class for generating a tkinter-based progress bar shown in an external
window.
PARAMETERS
----------
n_steps : int
- The total number of steps in the process whose progress is being
tracked.
title : str
- The name of the process whose progress is being tracked.
handle_n_exceeded : str; default "warning"
- How to act in the case that the total number of steps is exceeded by the
current step number. If "warning", a warning is raised. If "error", an
error is raised.
METHODS
-------
update_progress
- Increments the current step number in the total number of steps by one.
close
- Closes the progress bar window.
"""
def __init__(
self, n_steps: int, title: str, handle_n_exceeded: str = "warning"
) -> None:
self.n_steps = n_steps
self.title = title
self.handle_n_exceeded = handle_n_exceeded
self._step_n = 0
self.step_increment = 100 / n_steps
self.window = None
self.percent_label = None
self.progress_bar = None
self._sort_inputs()
self._create_bar()
def _sort_inputs(self) -> None:
"""Sorts inputs to the object.
RAISES
------
NotImplementedError
- Raised if the requested method for 'handle_n_exceeded' is not
supported.
"""
supported_handles = ["warning", "error"]
if self.handle_n_exceeded not in supported_handles:
raise NotImplementedError(
"Error: The method for handling instances of the total number "
f"of steps being exceeded '{self.handle_n_exceeded}' is not "
f"supported. Supported inputs are {supported_handles}."
)
def _create_bar(self) -> None:
"""Creates the tkinter root object and progress bar window with the
requested title."""
self.root = tkinter.Tk()
self.root.wm_attributes("-topmost", True)
self.progress_bar = ttk.Progressbar(self.root, length=250)
self.progress_bar.pack(padx=10, pady=10)
self.percent_label = tkinter.StringVar()
self.percent_label.set(self.progress)
ttk.Label(self.root, textvariable=self.percent_label).pack()
self.root.update()
@property
def progress(self) -> str:
"""Getter for returning the percentage completion of the progress bar as
a formatted string with the title.
RETURNS
-------
str
- The percentage completion of the progress bar, formatted into a
string with the structure: title; percentage.
"""
return f"{self.title}\n{str(int(self.progress_bar['value']))}% complete"
@property
def step_n(self) -> int:
"""Getter for returning the number of steps completed in the process
being followed."""
return self._step_n
@step_n.setter
def step_n(self, value) -> None:
"""Setter for the number of steps completed in the process being
followed.
RAISES
------
ValueError
- Raised if the current number of steps is greater than the total
number of steps specified when the object was created, and if
'handle_n_exceeded' was set to "error".
"""
if value > self.n_steps:
if self.handle_n_exceeded == "warning":
print(
"Warning: The maximum number of steps in the progress bar "
"has been exceeded.\n"
)
else:
raise ValueError(
"Error: The maximum number of steps in the progress bar "
"has been exceeded."
)
self._step_n = value
def update_progress(self, n_steps: int = 1) -> None:
"""Increments the step number of the process and updates the progress
bar value and label appropriately.
PARAMETERS
----------
n_steps : int; default 1
- The amount by which the step number should be updated.
"""
self.step_n += n_steps
self.progress_bar["value"] += self.step_increment * n_steps
self.percent_label.set(self.progress)
self.root.update()
def close(self) -> None:
"""Destroys the tkinter root object the progress bar is linked to."""
self.root.destroy()