Skip to content

Commit

Permalink
Merge pull request #100 from EddieTheHead/progress-bars
Browse files Browse the repository at this point in the history
Progress bars
  • Loading branch information
curiouswala authored Apr 24, 2022
2 parents dd4ca50 + b8d9aa6 commit 1758328
Show file tree
Hide file tree
Showing 3 changed files with 154 additions and 7 deletions.
27 changes: 21 additions & 6 deletions ampy/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@

import click
import dotenv
from progress_bar import PorgressBar
from progress_bar import PorgressBarBath

# Load AMPY_PORT et al from .ampy file
# Performed here because we need to beat click's decorators.
Expand Down Expand Up @@ -250,6 +252,14 @@ def put(local, remote):
# Check if path is a folder and do recursive copy of everything inside it.
# Otherwise it's a file and should simply be copied over.
if os.path.isdir(local):
# Create progress bar for each file
pb_bath = PorgressBarBath('Overall progress')
for parent, child_dirs, child_files in os.walk(local, followlinks=True):
for filename in child_files:
path = os.path.join(parent, filename)
size = os.stat(path).st_size
pb_bath.add_subjob(PorgressBar(name=path,total=size ))

# Directory copy, create the directory and walk all children to copy
# over the files.
board_files = files.Files(_board)
Expand All @@ -264,20 +274,25 @@ def put(local, remote):
except files.DirectoryExistsError:
# Ignore errors for directories that already exist.
pass

# Loop through all the files and put them on the board too.
for filename in child_files:
with open(os.path.join(parent, filename), "rb") as infile:
local_path = os.path.join(parent, filename)
with open(local_path, "rb") as infile:
remote_filename = posixpath.join(remote_parent, filename)
board_files.put(remote_filename, infile.read())


data = infile.read()
job = pb_bath.get_subjob(local_path)
callback = job.on_progress_done
board_files.put(remote_filename, data, callback)
else:
# File copy, open the file and copy its contents to the board.
# Put the file on the board.
with open(local, "rb") as infile:
data = infile.read()
progress = PorgressBar(name=local, total=len(data))
board_files = files.Files(_board)
board_files.put(remote, infile.read())

board_files.put(remote, data, progress.on_progress_done)
print('')

@cli.command()
@click.argument("remote_file")
Expand Down
6 changes: 5 additions & 1 deletion ampy/files.py
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ def mkdir(self, directory, exists_okay=False):
raise ex
self._pyboard.exit_raw_repl()

def put(self, filename, data):
def put(self, filename, data, progress_cb=None):
"""Create or update the specified file with the provided data.
"""
# Open the file for writing on the board and write chunks of data.
Expand All @@ -224,6 +224,10 @@ def put(self, filename, data):
if not chunk.startswith("b"):
chunk = "b" + chunk
self._pyboard.exec_("f.write({0})".format(chunk))
# notify caller how much has already been written
if hasattr(progress_cb, '__call__'):
progress_cb(chunk_size)

self._pyboard.exec_("f.close()")
self._pyboard.exit_raw_repl()

Expand Down
128 changes: 128 additions & 0 deletions ampy/progress_bar.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
import math
import time

class PorgressBar(object):
def __init__(self, name='', total=100, bar_width = 22, autorender=True):
self.total = total
self.progress = 0
self.name = name
self.bar_width = bar_width
self.autorender = autorender
self.parent_bath_job = None

def on_progress_done(self, progress):
self.progress += progress
if self.progress > self.total:
self.progress = self.total
if self.autorender:
self.print()
if self.parent_bath_job:
self.parent_bath_job.on_progress_done(progress)

def render(self):
if self.total == 0:
return
fraction = self.progress / self.total
done = math.floor( fraction * (self.bar_width-2))
percent = math.floor(fraction * 100)
return '[{}{}] {}{}%'.format( done * '#',
(self.bar_width - 2 - done ) * ' ',
(3 - len(str(percent)) ) * ' ',
percent)

def print( self ):
# start from newline begin
print('\r',end='')
# clear last line
print('' * (len(self.name) + 4 + self.bar_width), end='')
print('\r',end='')
# if progressbarr have a name, print it
if self.name != '':
print(self.name, ':', self.render(),end='')
else:
print(self.render)

class PorgressBarBath(object):
def __init__(self, name, bar_width = 40):
self.jobs = []
self.name = name
self.progress = PorgressBar(name, 0, bar_width=bar_width, autorender=False )
self.last_render_lines = 0
self.bar_width = bar_width

def get_subjob(self, name):
return next( (x for x in self.jobs if x.name == name), None)

def add_subjob(self, job):
if isinstance(job, PorgressBar):
job.parent_bath_job = self
job.autorender = False
job.bar_width = self.bar_width
self.jobs.append(job)
self.progress.total += job.total

def on_progress_done(self, progress):
self.progress.on_progress_done(progress)
self.print()

def print( self ):
max_line_width = 0
for job in self.jobs:
line_width = (len(job.name) + 6 + job.bar_width)
max_line_width = max( max_line_width, line_width)

# start from newline begin
print('\r',end='')
# return to print origin
if self.last_render_lines > 0:
print( '\r\u001b[{n}A\r'.format(n = self.last_render_lines), end='')

# print overall progress
print(self.name, ':', self.progress.render())
self.last_render_lines = 1
# print subjobs
for job in self.jobs:
job_bar = job.render()
# clear line
line_width = (len(job.name) + 4 + job.bar_width)
print('' * line_width, end='')
print('\r',end='')
print( job_bar, ':', ' ' * (max_line_width - line_width), job.name)
self.last_render_lines += 1



if __name__ == '__main__':
pb = PorgressBar('reading stuff', 200, 60, True)
pb_1 = PorgressBar('writing', 100, 22, True)
pb_2 = PorgressBar('sleeping', 20, 22, True)
pb_3 = PorgressBar('reading again', 200, 60, True)

bath = PorgressBarBath('Overall')
bath.add_subjob(pb)
bath.add_subjob(pb_1)
bath.add_subjob(pb_2)
bath.add_subjob(pb_3)

for i in range(0, 200):
pb.on_progress_done(1)
time.sleep(0.01)

time.sleep(1)

for i in range(0, 100):
pb_1.on_progress_done(1)
time.sleep(0.01)

time.sleep(1)
pb_2.on_progress_done(3)
time.sleep(0.3)
pb_2.on_progress_done(7)
time.sleep(0.3)
pb_2.on_progress_done(10)

for i in range(0, 200):
pb_3.on_progress_done(1)
time.sleep(0.01)

print('\n')

0 comments on commit 1758328

Please sign in to comment.