diff options
| author | Gavin Mak <gavinmak@google.com> | 2023-03-11 06:46:20 +0000 |
|---|---|---|
| committer | LUCI <gerrit-scoped@luci-project-accounts.iam.gserviceaccount.com> | 2023-03-22 17:46:28 +0000 |
| commit | ea2e330e43c182dc16b0111ebc69ee5a71ee4ce1 (patch) | |
| tree | dc33ba0e56825b3e007d0589891756724725a465 /progress.py | |
| parent | 1604cf255f8c1786a23388db6d5277ac7949a24a (diff) | |
| download | git-repo-ea2e330e43c182dc16b0111ebc69ee5a71ee4ce1.tar.gz | |
Format codebase with black and check formatting in CQ
Apply rules set by https://gerrit-review.googlesource.com/c/git-repo/+/362954/ across the codebase and fix any lingering errors caught
by flake8. Also check black formatting in run_tests (and CQ).
Bug: b/267675342
Change-Id: I972d77649dac351150dcfeb1cd1ad0ea2efc1956
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/363474
Reviewed-by: Mike Frysinger <vapier@google.com>
Tested-by: Gavin Mak <gavinmak@google.com>
Commit-Queue: Gavin Mak <gavinmak@google.com>
Diffstat (limited to 'progress.py')
| -rw-r--r-- | progress.py | 223 |
1 files changed, 122 insertions, 101 deletions
diff --git a/progress.py b/progress.py index 526ce6c1..d1a7c543 100644 --- a/progress.py +++ b/progress.py | |||
| @@ -22,115 +22,136 @@ _NOT_TTY = not os.isatty(2) | |||
| 22 | # This will erase all content in the current line (wherever the cursor is). | 22 | # This will erase all content in the current line (wherever the cursor is). |
| 23 | # It does not move the cursor, so this is usually followed by \r to move to | 23 | # It does not move the cursor, so this is usually followed by \r to move to |
| 24 | # column 0. | 24 | # column 0. |
| 25 | CSI_ERASE_LINE = '\x1b[2K' | 25 | CSI_ERASE_LINE = "\x1b[2K" |
| 26 | 26 | ||
| 27 | # This will erase all content in the current line after the cursor. This is | 27 | # This will erase all content in the current line after the cursor. This is |
| 28 | # useful for partial updates & progress messages as the terminal can display | 28 | # useful for partial updates & progress messages as the terminal can display |
| 29 | # it better. | 29 | # it better. |
| 30 | CSI_ERASE_LINE_AFTER = '\x1b[K' | 30 | CSI_ERASE_LINE_AFTER = "\x1b[K" |
| 31 | 31 | ||
| 32 | 32 | ||
| 33 | def duration_str(total): | 33 | def duration_str(total): |
| 34 | """A less noisy timedelta.__str__. | 34 | """A less noisy timedelta.__str__. |
| 35 | 35 | ||
| 36 | The default timedelta stringification contains a lot of leading zeros and | 36 | The default timedelta stringification contains a lot of leading zeros and |
| 37 | uses microsecond resolution. This makes for noisy output. | 37 | uses microsecond resolution. This makes for noisy output. |
| 38 | """ | 38 | """ |
| 39 | hours, rem = divmod(total, 3600) | 39 | hours, rem = divmod(total, 3600) |
| 40 | mins, secs = divmod(rem, 60) | 40 | mins, secs = divmod(rem, 60) |
| 41 | ret = '%.3fs' % (secs,) | 41 | ret = "%.3fs" % (secs,) |
| 42 | if mins: | 42 | if mins: |
| 43 | ret = '%im%s' % (mins, ret) | 43 | ret = "%im%s" % (mins, ret) |
| 44 | if hours: | 44 | if hours: |
| 45 | ret = '%ih%s' % (hours, ret) | 45 | ret = "%ih%s" % (hours, ret) |
| 46 | return ret | 46 | return ret |
| 47 | 47 | ||
| 48 | 48 | ||
| 49 | class Progress(object): | 49 | class Progress(object): |
| 50 | def __init__(self, title, total=0, units='', print_newline=False, delay=True, | 50 | def __init__( |
| 51 | quiet=False): | 51 | self, |
| 52 | self._title = title | 52 | title, |
| 53 | self._total = total | 53 | total=0, |
| 54 | self._done = 0 | 54 | units="", |
| 55 | self._start = time() | 55 | print_newline=False, |
| 56 | self._show = not delay | 56 | delay=True, |
| 57 | self._units = units | 57 | quiet=False, |
| 58 | self._print_newline = print_newline | 58 | ): |
| 59 | # Only show the active jobs section if we run more than one in parallel. | 59 | self._title = title |
| 60 | self._show_jobs = False | 60 | self._total = total |
| 61 | self._active = 0 | 61 | self._done = 0 |
| 62 | 62 | self._start = time() | |
| 63 | # When quiet, never show any output. It's a bit hacky, but reusing the | 63 | self._show = not delay |
| 64 | # existing logic that delays initial output keeps the rest of the class | 64 | self._units = units |
| 65 | # clean. Basically we set the start time to years in the future. | 65 | self._print_newline = print_newline |
| 66 | if quiet: | 66 | # Only show the active jobs section if we run more than one in parallel. |
| 67 | self._show = False | 67 | self._show_jobs = False |
| 68 | self._start += 2**32 | 68 | self._active = 0 |
| 69 | 69 | ||
| 70 | def start(self, name): | 70 | # When quiet, never show any output. It's a bit hacky, but reusing the |
| 71 | self._active += 1 | 71 | # existing logic that delays initial output keeps the rest of the class |
| 72 | if not self._show_jobs: | 72 | # clean. Basically we set the start time to years in the future. |
| 73 | self._show_jobs = self._active > 1 | 73 | if quiet: |
| 74 | self.update(inc=0, msg='started ' + name) | 74 | self._show = False |
| 75 | 75 | self._start += 2**32 | |
| 76 | def finish(self, name): | 76 | |
| 77 | self.update(msg='finished ' + name) | 77 | def start(self, name): |
| 78 | self._active -= 1 | 78 | self._active += 1 |
| 79 | 79 | if not self._show_jobs: | |
| 80 | def update(self, inc=1, msg=''): | 80 | self._show_jobs = self._active > 1 |
| 81 | self._done += inc | 81 | self.update(inc=0, msg="started " + name) |
| 82 | 82 | ||
| 83 | if _NOT_TTY or IsTraceToStderr(): | 83 | def finish(self, name): |
| 84 | return | 84 | self.update(msg="finished " + name) |
| 85 | 85 | self._active -= 1 | |
| 86 | if not self._show: | 86 | |
| 87 | if 0.5 <= time() - self._start: | 87 | def update(self, inc=1, msg=""): |
| 88 | self._show = True | 88 | self._done += inc |
| 89 | else: | 89 | |
| 90 | return | 90 | if _NOT_TTY or IsTraceToStderr(): |
| 91 | 91 | return | |
| 92 | if self._total <= 0: | 92 | |
| 93 | sys.stderr.write('\r%s: %d,%s' % ( | 93 | if not self._show: |
| 94 | self._title, | 94 | if 0.5 <= time() - self._start: |
| 95 | self._done, | 95 | self._show = True |
| 96 | CSI_ERASE_LINE_AFTER)) | 96 | else: |
| 97 | sys.stderr.flush() | 97 | return |
| 98 | else: | 98 | |
| 99 | p = (100 * self._done) / self._total | 99 | if self._total <= 0: |
| 100 | if self._show_jobs: | 100 | sys.stderr.write( |
| 101 | jobs = '[%d job%s] ' % (self._active, 's' if self._active > 1 else '') | 101 | "\r%s: %d,%s" % (self._title, self._done, CSI_ERASE_LINE_AFTER) |
| 102 | else: | 102 | ) |
| 103 | jobs = '' | 103 | sys.stderr.flush() |
| 104 | sys.stderr.write('\r%s: %2d%% %s(%d%s/%d%s)%s%s%s%s' % ( | 104 | else: |
| 105 | self._title, | 105 | p = (100 * self._done) / self._total |
| 106 | p, | 106 | if self._show_jobs: |
| 107 | jobs, | 107 | jobs = "[%d job%s] " % ( |
| 108 | self._done, self._units, | 108 | self._active, |
| 109 | self._total, self._units, | 109 | "s" if self._active > 1 else "", |
| 110 | ' ' if msg else '', msg, | 110 | ) |
| 111 | CSI_ERASE_LINE_AFTER, | 111 | else: |
| 112 | '\n' if self._print_newline else '')) | 112 | jobs = "" |
| 113 | sys.stderr.flush() | 113 | sys.stderr.write( |
| 114 | 114 | "\r%s: %2d%% %s(%d%s/%d%s)%s%s%s%s" | |
| 115 | def end(self): | 115 | % ( |
| 116 | if _NOT_TTY or IsTraceToStderr() or not self._show: | 116 | self._title, |
| 117 | return | 117 | p, |
| 118 | 118 | jobs, | |
| 119 | duration = duration_str(time() - self._start) | 119 | self._done, |
| 120 | if self._total <= 0: | 120 | self._units, |
| 121 | sys.stderr.write('\r%s: %d, done in %s%s\n' % ( | 121 | self._total, |
| 122 | self._title, | 122 | self._units, |
| 123 | self._done, | 123 | " " if msg else "", |
| 124 | duration, | 124 | msg, |
| 125 | CSI_ERASE_LINE_AFTER)) | 125 | CSI_ERASE_LINE_AFTER, |
| 126 | sys.stderr.flush() | 126 | "\n" if self._print_newline else "", |
| 127 | else: | 127 | ) |
| 128 | p = (100 * self._done) / self._total | 128 | ) |
| 129 | sys.stderr.write('\r%s: %3d%% (%d%s/%d%s), done in %s%s\n' % ( | 129 | sys.stderr.flush() |
| 130 | self._title, | 130 | |
| 131 | p, | 131 | def end(self): |
| 132 | self._done, self._units, | 132 | if _NOT_TTY or IsTraceToStderr() or not self._show: |
| 133 | self._total, self._units, | 133 | return |
| 134 | duration, | 134 | |
| 135 | CSI_ERASE_LINE_AFTER)) | 135 | duration = duration_str(time() - self._start) |
| 136 | sys.stderr.flush() | 136 | if self._total <= 0: |
| 137 | sys.stderr.write( | ||
| 138 | "\r%s: %d, done in %s%s\n" | ||
| 139 | % (self._title, self._done, duration, CSI_ERASE_LINE_AFTER) | ||
| 140 | ) | ||
| 141 | sys.stderr.flush() | ||
| 142 | else: | ||
| 143 | p = (100 * self._done) / self._total | ||
| 144 | sys.stderr.write( | ||
| 145 | "\r%s: %3d%% (%d%s/%d%s), done in %s%s\n" | ||
| 146 | % ( | ||
| 147 | self._title, | ||
| 148 | p, | ||
| 149 | self._done, | ||
| 150 | self._units, | ||
| 151 | self._total, | ||
| 152 | self._units, | ||
| 153 | duration, | ||
| 154 | CSI_ERASE_LINE_AFTER, | ||
| 155 | ) | ||
| 156 | ) | ||
| 157 | sys.stderr.flush() | ||
