progress.py 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. # Copyright (C) 2009 The Android Open Source Project
  2. #
  3. # Licensed under the Apache License, Version 2.0 (the "License");
  4. # you may not use this file except in compliance with the License.
  5. # You may obtain a copy of the License at
  6. #
  7. # http://www.apache.org/licenses/LICENSE-2.0
  8. #
  9. # Unless required by applicable law or agreed to in writing, software
  10. # distributed under the License is distributed on an "AS IS" BASIS,
  11. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. # See the License for the specific language governing permissions and
  13. # limitations under the License.
  14. import os
  15. import sys
  16. from time import time
  17. from repo_trace import IsTrace
  18. _NOT_TTY = not os.isatty(2)
  19. # This will erase all content in the current line (wherever the cursor is).
  20. # It does not move the cursor, so this is usually followed by \r to move to
  21. # column 0.
  22. CSI_ERASE_LINE = '\x1b[2K'
  23. class Progress(object):
  24. def __init__(self, title, total=0, units='', print_newline=False,
  25. always_print_percentage=False):
  26. self._title = title
  27. self._total = total
  28. self._done = 0
  29. self._lastp = -1
  30. self._start = time()
  31. self._show = False
  32. self._units = units
  33. self._print_newline = print_newline
  34. self._always_print_percentage = always_print_percentage
  35. def update(self, inc=1, msg=''):
  36. self._done += inc
  37. if _NOT_TTY or IsTrace():
  38. return
  39. if not self._show:
  40. if 0.5 <= time() - self._start:
  41. self._show = True
  42. else:
  43. return
  44. if self._total <= 0:
  45. sys.stderr.write('%s\r%s: %d,' % (
  46. CSI_ERASE_LINE,
  47. self._title,
  48. self._done))
  49. sys.stderr.flush()
  50. else:
  51. p = (100 * self._done) / self._total
  52. if self._lastp != p or self._always_print_percentage:
  53. self._lastp = p
  54. sys.stderr.write('%s\r%s: %3d%% (%d%s/%d%s)%s%s%s' % (
  55. CSI_ERASE_LINE,
  56. self._title,
  57. p,
  58. self._done, self._units,
  59. self._total, self._units,
  60. ' ' if msg else '', msg,
  61. "\n" if self._print_newline else ""))
  62. sys.stderr.flush()
  63. def end(self):
  64. if _NOT_TTY or IsTrace() or not self._show:
  65. return
  66. if self._total <= 0:
  67. sys.stderr.write('%s\r%s: %d, done.\n' % (
  68. CSI_ERASE_LINE,
  69. self._title,
  70. self._done))
  71. sys.stderr.flush()
  72. else:
  73. p = (100 * self._done) / self._total
  74. sys.stderr.write('%s\r%s: %3d%% (%d%s/%d%s), done.\n' % (
  75. CSI_ERASE_LINE,
  76. self._title,
  77. p,
  78. self._done, self._units,
  79. self._total, self._units))
  80. sys.stderr.flush()