mirror of https://github.com/chriskiehl/Gooey.git
Browse Source
Elapsed / Remaining Time on Progress Bar
Elapsed / Remaining Time on Progress Bar
parent 00e0f3e7c6
author Jack McKew <jackmckew2@gmail.com> 1594344614 +1000
committer Jack McKew <jackmckew2@gmail.com> 1594346638 +1000
Elapsed / Remaining Time on Progress Bar
parent 00e0f3e7c6434240ffe02522a0be2daf8c5b456c
author Fizban <jackmckew2@gmail.com> 1593182730 +1000
committer Fizban <jackmckew2@gmail.com> 1593246420 +1000
parent 00e0f3e7c6434240ffe02522a0be2daf8c5b456c
author Fizban <jackmckew2@gmail.com> 1593182730 +1000
committer Fizban <jackmckew2@gmail.com> 1593246359 +1000
Elapsed / Remaining Time on Progress Bar
Elapsed / Remaining Time on Progress Bar
Time Remaining Text for Progress
Time remaining somewhat working
Time format working
Add tests and pythn 2.7 compat
Incase python 2 import perf counter in func
Fix flickering text and align
Remove transactUI
Add new decorators
Update time remaining notes in README
Amend tests with new arguments
Remove unused import
Separate into time module
Move to dictionary structure options
Explicitly show time text
Amend tests for separate module
Integration test - missing on complete tests
Remove old code
Elapsed / Remaining Time on Progress Bar
parent 00e0f3e7c6434240ffe02522a0be2daf8c5b456c
author Fizban <jackmckew2@gmail.com> 1593182730 +1000
committer Fizban <jackmckew2@gmail.com> 1593246420 +1000
parent 00e0f3e7c6434240ffe02522a0be2daf8c5b456c
author Fizban <jackmckew2@gmail.com> 1593182730 +1000
committer Fizban <jackmckew2@gmail.com> 1593246359 +1000
Elapsed / Remaining Time on Progress Bar
Elapsed / Remaining Time on Progress Bar
Time Remaining Text for Progress
Time remaining somewhat working
Time format working
Add tests and pythn 2.7 compat
Incase python 2 import perf counter in func
Fix flickering text and align
Remove transactUI
Add new decorators
Update time remaining notes in README
Amend tests with new arguments
Remove unused import
Separate into time module
Move to dictionary structure options
Explicitly show time text
Amend tests for separate module
Remove old code
Pass testdata as dict instead of kwargs
Merge dictionaries for defaults
Test almost working
Delete settings.json
Revert "Test almost working"
This reverts commit f17d50681cae664719f67a7e8cc0b1feaf1ac4c7.
Back to working state
Remove unhelpful test
Update docs
Working without updated test
Add tests for time remaining text
Elapsed / Remaining Time on Progress Bar
parent 00e0f3e7c6434240ffe02522a0be2daf8c5b456c
author Jack McKew <jackmckew2@gmail.com> 1594344614 +1000
committer Jack McKew <jackmckew2@gmail.com> 1594346638 +1000
Elapsed / Remaining Time on Progress Bar
parent 00e0f3e7c6434240ffe02522a0be2daf8c5b456c
author Fizban <jackmckew2@gmail.com> 1593182730 +1000
committer Fizban <jackmckew2@gmail.com> 1593246420 +1000
parent 00e0f3e7c6434240ffe02522a0be2daf8c5b456c
author Fizban <jackmckew2@gmail.com> 1593182730 +1000
committer Fizban <jackmckew2@gmail.com> 1593246359 +1000
Elapsed / Remaining Time on Progress Bar
Elapsed / Remaining Time on Progress Bar
Time Remaining Text for Progress
Time remaining somewhat working
Time format working
Add tests and pythn 2.7 compat
Incase python 2 import perf counter in func
Fix flickering text and align
Remove transactUI
Add new decorators
Update time remaining notes in README
Amend tests with new arguments
Remove unused import
Separate into time module
Move to dictionary structure options
Explicitly show time text
Amend tests for separate module
Integration test - missing on complete tests
Remove old code
Elapsed / Remaining Time on Progress Bar
parent 00e0f3e7c6434240ffe02522a0be2daf8c5b456c
author Fizban <jackmckew2@gmail.com> 1593182730 +1000
committer Fizban <jackmckew2@gmail.com> 1593246420 +1000
parent 00e0f3e7c6434240ffe02522a0be2daf8c5b456c
author Fizban <jackmckew2@gmail.com> 1593182730 +1000
committer Fizban <jackmckew2@gmail.com> 1593246359 +1000
Elapsed / Remaining Time on Progress Bar
Elapsed / Remaining Time on Progress Bar
Time Remaining Text for Progress
Time remaining somewhat working
Time format working
Add tests and pythn 2.7 compat
Incase python 2 import perf counter in func
Fix flickering text and align
Remove transactUI
Add new decorators
Update time remaining notes in README
Amend tests with new arguments
Remove unused import
Separate into time module
Move to dictionary structure options
Explicitly show time text
Amend tests for separate module
Remove old code
Pass testdata as dict instead of kwargs
Merge dictionaries for defaults
Test almost working
Delete settings.json
Revert "Test almost working"
This reverts commit f17d50681cae664719f67a7e8cc0b1feaf1ac4c7.
Back to working state
Remove unhelpful test
Update docs
Working without updated test
Add tests for time remaining text
Remove artifact from squashing
Amend artifacts
Handle no progress and tidy up footer label
1.0.5-release-candidate
Jack McKew
4 years ago
committed by
Chris
12 changed files with 329 additions and 57 deletions
Unified View
Diff Options
-
118README.md
-
19gooey/gui/components/footer.py
-
15gooey/gui/containers/application.py
-
1gooey/gui/events.py
-
4gooey/gui/processor.py
-
24gooey/gui/util/functional.py
-
96gooey/gui/util/time.py
-
3gooey/python_bindings/config_generator.py
-
4gooey/python_bindings/gooey_decorator.py
-
7gooey/tests/test_processor.py
-
63gooey/tests/test_time_remaining.py
-
32gooey/tests/test_util.py
@ -1,6 +1,30 @@ |
|||||
|
''' |
||||
|
Utils for functional methodologies throughout Gooey |
||||
|
|
||||
|
''' |
||||
|
|
||||
|
|
||||
|
def merge_dictionaries(x,y): |
||||
|
""" |
||||
|
Merge 2 dictionaries with y taking overwriting x if a key collision is found |
||||
|
|
||||
|
This is mainly useful for maintaining the dictionary arguments to allow for more expressive & extensible arguments. |
||||
|
https://stackoverflow.com/questions/38987/how-do-i-merge-two-dictionaries-in-a-single-expression-in-python-taking-union-o |
||||
|
|
||||
|
Args: |
||||
|
x (dict): Input dictionary |
||||
|
y (dict): Input dictionary |
||||
|
|
||||
|
Returns: |
||||
|
The combined dictionary of x & y with y taking preference on the occasion of key collision |
||||
|
""" |
||||
|
if x is None: |
||||
|
x = {} |
||||
|
if y is None: |
||||
|
y = {} |
||||
|
try: |
||||
|
return {**x,**y} |
||||
|
except: |
||||
|
z = x.copy() |
||||
|
z.update(y) |
||||
|
return z |
@ -0,0 +1,96 @@ |
|||||
|
""" |
||||
|
Module for evaluating time elapsed & time remaining from progress |
||||
|
""" |
||||
|
import wx |
||||
|
from gooey.gui.pubsub import pub |
||||
|
from gooey.gui import events |
||||
|
|
||||
|
class Timing(object): |
||||
|
|
||||
|
def __init__(self, parent): |
||||
|
self.startTime = 0 |
||||
|
self.estimatedRemaining = None |
||||
|
self.wxTimer = wx.Timer(parent) |
||||
|
self.parent = parent |
||||
|
parent.Bind(wx.EVT_TIMER, self.publishTime, self.wxTimer) |
||||
|
|
||||
|
pub.subscribe(events.PROGRESS_UPDATE, self._updateEstimate) |
||||
|
|
||||
|
def _updateEstimate(self, *args, **kwargs): |
||||
|
prog = kwargs.get('progress') |
||||
|
if(not prog): |
||||
|
self.estimatedRemaining = None |
||||
|
return |
||||
|
if(prog > 0): |
||||
|
self.estimatedRemaining = estimate_time_remaining(prog,self.startTime) |
||||
|
|
||||
|
def publishTime(self, *args, **kwargs): |
||||
|
pub.send_message( |
||||
|
events.TIME_UPDATE, |
||||
|
start=self.startTime, |
||||
|
current=get_current_time(), |
||||
|
elapsed_time=format_interval(get_elapsed_time(self.startTime)), |
||||
|
estimatedRemaining=format_interval(self.estimatedRemaining)) |
||||
|
|
||||
|
def start(self): |
||||
|
self.startTime = get_current_time() |
||||
|
self.estimatedRemaining = None |
||||
|
self.wxTimer.Start() |
||||
|
|
||||
|
def stop(self): |
||||
|
self.wxTimer.Stop() |
||||
|
|
||||
|
def format_interval(timeValue): |
||||
|
""" |
||||
|
Formats a number of seconds as a clock time, [H:]MM:SS |
||||
|
Parameters |
||||
|
---------- |
||||
|
t : int |
||||
|
Number of seconds. |
||||
|
Returns |
||||
|
------- |
||||
|
out : str |
||||
|
[H:]MM:SS |
||||
|
""" |
||||
|
# https://github.com/tqdm/tqdm/blob/0cd9448b2bc08125e74538a2aea6af42ee1a7b6f/tqdm/std.py#L228 |
||||
|
try: |
||||
|
mins, s = divmod(int(timeValue), 60) |
||||
|
h, m = divmod(mins, 60) |
||||
|
if h: |
||||
|
return '{0:d}:{1:02d}:{2:02d}'.format(h, m, s) |
||||
|
else: |
||||
|
return '{0:02d}:{1:02d}'.format(m, s) |
||||
|
except: |
||||
|
return None |
||||
|
|
||||
|
def get_elapsed_time(startTime): |
||||
|
""" |
||||
|
Get elapsed time in form of seconds. Provide a start time in seconds as float. |
||||
|
|
||||
|
Args: |
||||
|
startTime (float): Start time to compare against in seconds. |
||||
|
|
||||
|
Returns: |
||||
|
float: Time between start time and now |
||||
|
""" |
||||
|
return get_current_time() - startTime |
||||
|
|
||||
|
def estimate_time_remaining(progress,startTime): |
||||
|
# https://github.com/tqdm/tqdm/blob/0cd9448b2bc08125e74538a2aea6af42ee1a7b6f/tqdm/std.py#L392 |
||||
|
# https://github.com/tqdm/tqdm/blob/0cd9448b2bc08125e74538a2aea6af42ee1a7b6f/tqdm/std.py#L417 |
||||
|
_rate = progress / get_elapsed_time(startTime) |
||||
|
return ((100 - progress) / _rate) |
||||
|
|
||||
|
def get_current_time(): |
||||
|
""" |
||||
|
Returns a float of the current time in seconds. Attempt to import perf_counter (more accurate in 3.4+), otherwise utilise timeit. |
||||
|
|
||||
|
Returns: |
||||
|
float: Current time in seconds from performance counter. |
||||
|
""" |
||||
|
try: |
||||
|
from time import perf_counter |
||||
|
return perf_counter() |
||||
|
except: |
||||
|
import timeit |
||||
|
return timeit.default_timer() |
@ -0,0 +1,63 @@ |
|||||
|
import time |
||||
|
import unittest |
||||
|
from argparse import ArgumentParser |
||||
|
from itertools import * |
||||
|
|
||||
|
from tests.harness import instrumentGooey |
||||
|
|
||||
|
class TestFooterTimeRemaining(unittest.TestCase): |
||||
|
|
||||
|
def make_parser(self): |
||||
|
parser = ArgumentParser(description='description') |
||||
|
return parser |
||||
|
|
||||
|
def test_time_remaining_visibility(self): |
||||
|
for testdata in self.testcases(): |
||||
|
with self.subTest(testdata): |
||||
|
with instrumentGooey(self.make_parser(), timing_options=testdata) as (app, gooeyApp): |
||||
|
|
||||
|
gooeyApp.showConsole() |
||||
|
footer = gooeyApp.footer |
||||
|
|
||||
|
|
||||
|
self.assertEqual( |
||||
|
footer.time_remaining_text.Shown, |
||||
|
testdata.get('show_time_remaining',False) |
||||
|
) |
||||
|
|
||||
|
def test_time_remaining_visibility_on_complete(self): |
||||
|
for testdata in self.testcases(): |
||||
|
with self.subTest(testdata): |
||||
|
with instrumentGooey(self.make_parser(), timing_options=testdata) as (app, gooeyApp): |
||||
|
|
||||
|
gooeyApp.showComplete() |
||||
|
footer = gooeyApp.footer |
||||
|
|
||||
|
|
||||
|
if not testdata.get('show_time_remaining') and testdata: |
||||
|
self.assertEqual( |
||||
|
footer.time_remaining_text.Shown, |
||||
|
testdata.get('hide_time_remaining_on_complete',True) |
||||
|
) |
||||
|
else: |
||||
|
return True |
||||
|
|
||||
|
def testcases(self): |
||||
|
""" |
||||
|
Generate a powerset of all possible combinations of |
||||
|
the header parameters (empty, some present, all present, all combos) |
||||
|
""" |
||||
|
iterable = product(['show_time_remaining', 'hide_time_remaining_on_complete'], [True, False]) |
||||
|
allCombinations = list(powerset(iterable)) |
||||
|
return [{k: v for k,v in args} |
||||
|
for args in allCombinations] |
||||
|
|
||||
|
|
||||
|
def powerset(iterable): |
||||
|
"powerset([1,2,3]) --> () (1,) (2,) (3,) (1,2) (1,3) (2,3) (1,2,3)" |
||||
|
s = list(iterable) |
||||
|
return chain.from_iterable(combinations(s, r) for r in range(len(s)+1)) |
||||
|
|
||||
|
|
||||
|
if __name__ == '__main__': |
||||
|
unittest.main() |
@ -0,0 +1,32 @@ |
|||||
|
import re |
||||
|
import unittest |
||||
|
|
||||
|
from gooey.gui.util.time import get_current_time,get_elapsed_time,estimate_time_remaining,format_interval |
||||
|
|
||||
|
|
||||
|
class TestTimeUtil(unittest.TestCase): |
||||
|
def test_time_elapsed(self): |
||||
|
# Check that time elapsed is greater than zero |
||||
|
_start_time = get_current_time() |
||||
|
elapsed = get_elapsed_time(_start_time) |
||||
|
self.assertGreater(elapsed,0) |
||||
|
|
||||
|
def test_time_remaining(self): |
||||
|
# Check that time elapsed is greater than zero |
||||
|
_start_time = get_current_time() |
||||
|
remaining = estimate_time_remaining(30,_start_time) |
||||
|
self.assertGreater(remaining,0) |
||||
|
|
||||
|
def test_current_time(self): |
||||
|
# Test that current time is greater than zero |
||||
|
_start_time = get_current_time() |
||||
|
self.assertGreater(_start_time,0) |
||||
|
|
||||
|
|
||||
|
def test_format_interval(self): |
||||
|
# Test same as TQDM https://github.com/tqdm/tqdm/blob/0cd9448b2bc08125e74538a2aea6af42ee1a7b6f/tqdm/tests/tests_tqdm.py#L234 |
||||
|
# but in unittest form |
||||
|
|
||||
|
self.assertEqual(format_interval(60), '01:00') |
||||
|
self.assertEqual(format_interval(6160), '1:42:40') |
||||
|
self.assertEqual(format_interval(238113), '66:08:33') |
Write
Preview
Loading…
Cancel
Save