-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
➕ Added average ETA (progress) + several tweaks
- Loading branch information
Showing
33 changed files
with
810 additions
and
221 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
Metadata-Version: 2.1 | ||
Name: LRFutils | ||
Version: 0.0.11 | ||
Summary: Just a custom library to share with some colleagues. Use it at your own risks. | ||
Home-page: https://github.com/LeiRoF/Utils | ||
Author: Leirof | ||
Author-email: [email protected] | ||
Classifier: Programming Language :: Python :: 3 | ||
Classifier: License :: OSI Approved :: MIT License | ||
Classifier: Operating System :: OS Independent | ||
Classifier: Intended Audience :: Developers | ||
Requires-Python: >=3.10.0 | ||
License-File: LICENSE |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
LICENSE | ||
README.md | ||
setup.py | ||
LRFutils/__init__.py | ||
LRFutils/archive.py | ||
LRFutils/color.py | ||
LRFutils/logs.py | ||
LRFutils/progress.py | ||
LRFutils/term.py | ||
LRFutils.egg-info/PKG-INFO | ||
LRFutils.egg-info/SOURCES.txt | ||
LRFutils.egg-info/dependency_links.txt | ||
LRFutils.egg-info/requires.txt | ||
LRFutils.egg-info/top_level.txt |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
gitpython | ||
regex |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
LRFutils |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,4 +2,4 @@ | |
from .color import * | ||
from .term import * | ||
from .progress import * | ||
from .log import * | ||
from .logs import * |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,54 +1,53 @@ | ||
import re | ||
|
||
class Color: | ||
NC = '\033[0m' # No Color, reset all | ||
|
||
Bold = '\033[1m' | ||
Underlined = '\033[4m' | ||
Blink = '\033[5m' | ||
Inverted = '\033[7m' | ||
Hidden = '\033[8m' | ||
|
||
Black = '\033[30m' | ||
Red = '\033[31m' | ||
Green = '\033[32m' | ||
Yellow = '\033[33m' | ||
Blue = '\033[34m' | ||
Purple = '\033[35m' | ||
Cyan = '\033[36m' | ||
LightGray = '\033[37m' | ||
|
||
Gray = "\u001b[30;1m" | ||
LightRed = "\u001b[31;1m" | ||
LightGreen = "\u001b[32;1m" | ||
LightYellow = "\u001b[33;1m" | ||
LightBlue = "\u001b[34;1m" | ||
LightMagenta = "\u001b[35;1m" | ||
LightCyan = "\u001b[36;1m" | ||
White = "\u001b[37;1m" | ||
|
||
|
||
on_Black = "\u001b[40m" | ||
on_Red = "\u001b[41m" | ||
on_Green = "\u001b[42m" | ||
on_Yellow = "\u001b[43m" | ||
on_Blue = "\u001b[44m" | ||
on_Magenta = "\u001b[45m" | ||
on_Cyan = "\u001b[46m" | ||
on_LightGray = "\u001b[47m" | ||
|
||
|
||
on_Gray = "\u001b[40;1m" | ||
on_LightRed = "\u001b[41;1m" | ||
on_LightGreen = "\u001b[42;1m" | ||
on_LightYellow = "\u001b[43;1m" | ||
on_LightBlue = "\u001b[44;1m" | ||
on_LightMagenta = "\u001b[45;1m" | ||
on_LightCyan = "\u001b[46;1m" | ||
on_White = "\u001b[47;1m" | ||
|
||
def clear(txt): | ||
txt = re.sub("\033\[[0-9][0-9]?m", "", txt) | ||
txt = re.sub("\\u001b\[[0-9][0-9]?m", "", txt) | ||
txt = re.sub("\\u001b\[[0-9][0-9]?;1m", "", txt) | ||
return txt | ||
NC = '\033[0m' # No Color, reset all | ||
|
||
Bold = '\033[1m' | ||
Underlined = '\033[4m' | ||
Blink = '\033[5m' | ||
Inverted = '\033[7m' | ||
Hidden = '\033[8m' | ||
|
||
Black = '\033[30m' | ||
Red = '\033[31m' | ||
Green = '\033[32m' | ||
Yellow = '\033[33m' | ||
Blue = '\033[34m' | ||
Purple = '\033[35m' | ||
Cyan = '\033[36m' | ||
LightGray = '\033[37m' | ||
|
||
Gray = "\u001b[30;1m" | ||
LightRed = "\u001b[31;1m" | ||
LightGreen = "\u001b[32;1m" | ||
LightYellow = "\u001b[33;1m" | ||
LightBlue = "\u001b[34;1m" | ||
LightMagenta = "\u001b[35;1m" | ||
LightCyan = "\u001b[36;1m" | ||
White = "\u001b[37;1m" | ||
|
||
|
||
on_Black = "\u001b[40m" | ||
on_Red = "\u001b[41m" | ||
on_Green = "\u001b[42m" | ||
on_Yellow = "\u001b[43m" | ||
on_Blue = "\u001b[44m" | ||
on_Magenta = "\u001b[45m" | ||
on_Cyan = "\u001b[46m" | ||
on_LightGray = "\u001b[47m" | ||
|
||
|
||
on_Gray = "\u001b[40;1m" | ||
on_LightRed = "\u001b[41;1m" | ||
on_LightGreen = "\u001b[42;1m" | ||
on_LightYellow = "\u001b[43;1m" | ||
on_LightBlue = "\u001b[44;1m" | ||
on_LightMagenta = "\u001b[45;1m" | ||
on_LightCyan = "\u001b[46;1m" | ||
on_White = "\u001b[47;1m" | ||
|
||
def clear(txt): | ||
txt = re.sub("\033\[[0-9][0-9]?m", "", txt) | ||
txt = re.sub("\\u001b\[[0-9][0-9]?m", "", txt) | ||
txt = re.sub("\\u001b\[[0-9][0-9]?;1m", "", txt) | ||
return txt |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,74 +1,119 @@ | ||
from .color import Color | ||
from . import color | ||
from time import time | ||
import datetime | ||
|
||
class Bar(): | ||
def __init__(self, max = 1, width = 80, prefix = "", eta = True, decimals = 0, duration = True): | ||
|
||
|
||
|
||
# ________________________________________________________________________________ | ||
# Create a progress bar | ||
|
||
def __init__(self, max:float|int = 1, width:int = 80, prefix:str = "", eta:bool = True, decimals:int = 0, show_duration:bool = True, average_ETA:int = 10): | ||
self.max = max | ||
self.width = width if type(width) == int else 80 | ||
self.width = width if isinstance(width,int) else 80 | ||
self.prefix = prefix | ||
self.eta = eta | ||
self.decimals = decimals | ||
self.lastProgress = 0 | ||
self.lastUpdate = None | ||
self.previous_progress = [0] | ||
self.previous_update = [] | ||
self.lastETA = "-" | ||
self.start_at = time() | ||
self.duration = duration | ||
self.duration = show_duration | ||
self.average_ETA = average_ETA | ||
|
||
|
||
# ________________________________________________________________________________ | ||
# Compute the ETA | ||
|
||
def update_eta(self, progress): | ||
if self.lastUpdate is not None and time()-self.lastUpdate < 1: return self.lastETA | ||
|
||
progression = progress - self.lastProgress | ||
left = (self.max-progress) | ||
# Get index of the i-th revious update to average the ETA on i updates | ||
if len(self.previous_progress) <= self.average_ETA: | ||
i = 0 | ||
else: | ||
i = -self.average_ETA | ||
|
||
# Compute progression since the i-th previous update | ||
progression = progress - self.previous_progress[i] | ||
todo = self.max - progress | ||
|
||
if progression == 0 or self.lastUpdate is None: | ||
self.lastUpdate = time() | ||
self.lastProgress = progress | ||
# If there is no progression or the bar was just created, it update the data but return the same ETA | ||
if progression == 0 or self.previous_update == []: | ||
self.previous_update.append(time()) | ||
self.previous_progress.append(progress) | ||
self.lastETA = "-" | ||
return self.lastETA | ||
|
||
seconds = left/progression * (time() - self.lastUpdate) | ||
self.lastUpdate = time() | ||
self.lastProgress = progress | ||
if seconds < 0: self.lastETA = "-" | ||
else: self.lastETA = str(datetime.timedelta(seconds=seconds)).split(".")[0] | ||
# If the bar was updated less than one second before, | ||
# we don't update it again to not slow the program | ||
if time()-self.previous_update[-1] < 1: | ||
return self.lastETA | ||
|
||
# Compute the ETA in seconds | ||
try: | ||
seconds = todo / progression * (time() - self.previous_update[i]) | ||
except: | ||
print(len(self.previous_update), i) | ||
|
||
# Update bar data | ||
self.previous_update.append(time()) | ||
self.previous_progress.append(progress) | ||
|
||
# If the ETA is negative, then we show an undefined ETA | ||
if seconds < 0: | ||
self.lastETA = "-" | ||
# Else we return the number of seconds | ||
else: | ||
self.lastETA = str(datetime.timedelta(seconds=seconds)).split(".")[0] | ||
|
||
return self.lastETA | ||
|
||
|
||
|
||
# ________________________________________________________________________________ | ||
# Update the progress bar | ||
|
||
def __call__(self, progress: float, prefix=None, stop=False): | ||
if prefix is None: prefix = self.prefix | ||
else: prefix = str(prefix) | ||
|
||
progress_normed = progress / self.max | ||
if progress == self.max : stop = True | ||
color = Color.Yellow if stop and progress_normed != 1 else Color.LightGreen | ||
color_bar = color.Yellow if stop and progress_normed != 1 else color.LightGreen | ||
|
||
if stop: end = "\n" | ||
else: end = "\r" | ||
|
||
if type(progress) == float: progress = round(progress, self.decimals) | ||
percent = f" {color}{round(progress_normed*100,self.decimals) if self.decimals > 0 else int(progress_normed*100)}%" | ||
frac = f" {Color.LightRed}{progress}/{self.max}" if self.max is not None else '' | ||
eta = f" {Color.NC}eta {Color.Blue}{self.update_eta(progress)}" if not stop else '' | ||
duration = f" {Color.Purple}{str(datetime.timedelta(seconds=time() - self.start_at)).split('.')[0]}" if self.duration else '' | ||
percent = f" {color_bar}{round(progress_normed*100,self.decimals) if self.decimals > 0 else int(progress_normed*100)}%" | ||
frac = f" {color.LightRed}{progress}/{self.max}" if self.max is not None else '' | ||
eta = f" {color.NC}eta {color.Blue}{self.update_eta(progress)}" if not stop else '' | ||
duration = f" {color.Purple}{str(datetime.timedelta(seconds=time() - self.start_at)).split('.')[0]}" if self.duration else '' | ||
|
||
prefix = '' if prefix == '' else Color.NC + prefix + ' ' | ||
prefix = '' if prefix == '' else color.NC + prefix + ' ' | ||
suffix = f"{percent}{frac}{duration}{eta}" | ||
|
||
barwidth = self.width - len(Color.clear(suffix)) - len(Color.clear(prefix)) | ||
barwidth = self.width - len(color.clear(suffix)) - len(color.clear(prefix)) | ||
barwidth = max(barwidth,10) | ||
|
||
currentBar = int(round(min(progress_normed*barwidth,barwidth))) | ||
minBar = int(min(progress_normed*barwidth,barwidth)) | ||
|
||
if progress_normed == 0: bar = Color.White + '━' * barwidth | ||
elif progress_normed == 1: bar = Color.LightGreen + '━' * barwidth | ||
elif currentBar == minBar: bar = color + '━' * currentBar + Color.White + '╺' + Color.White + '━' * (barwidth - currentBar - 1) | ||
else: bar = color + '━' * (currentBar - 1) + color + '╸' + Color.White + '━' * (barwidth - currentBar) | ||
if progress_normed == 0: bar = color.White + '━' * barwidth | ||
elif progress_normed == 1: bar = color.LightGreen + '━' * barwidth | ||
elif currentBar == minBar: bar = color_bar + '━' * currentBar + color.White + '╺' + color.White + '━' * (barwidth - currentBar - 1) | ||
else: bar = color_bar + '━' * (currentBar - 1) + color_bar + '╸' + color.White + '━' * (barwidth - currentBar) | ||
|
||
msg = f"{prefix}{bar}{suffix}{Color.NC}" | ||
msg = f"{prefix}{bar}{suffix}{color.NC}" | ||
print(msg, end=end) | ||
|
||
|
||
|
||
# ________________________________________________________________________________ | ||
# Stop the progress bar | ||
|
||
def stop(self): | ||
self(self.lastProgress, stop=True) | ||
self.lastProgress = 0 | ||
self(self.previous_progress[-1], stop=True) | ||
self.previous_progress = [0] | ||
self.lastUpdate = None |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
Metadata-Version: 2.1 | ||
Name: Leirof | ||
Version: 0.0.11 | ||
Summary: Just a custom library to share with some colleagues. Use it at your own risks. | ||
Home-page: https://github.com/LeiRoF/LRFutils | ||
License: MIT | ||
Project-URL: Bug Tracker, https://github.com/LeiRoF/LRFutils/issues | ||
Classifier: [ | ||
Classifier: "Programming Language :: Python :: 3", | ||
Classifier: "License :: OSI Approved :: MIT License", | ||
Classifier: "Operating System :: OS Independent", | ||
Classifier: 'Intended Audience :: Developers' | ||
Classifier: ] | ||
Requires-Python: >=3.10 | ||
License-File: LICENSE |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
gitpython | ||
regex |
Oops, something went wrong.