Permalink
Browse files

added Python 2.4 support + reorganized library

 - removed minor issues which blocked Python 2.4 support
 - split library up into logical units
 - cleaned up setup

--HG--
rename : LICENSE => LICENSE.txt
rename : README => README.txt
  • Loading branch information...
1 parent f691ebd commit 06acded56f46dc8f2a7646f04a351e0945bdc65e @terencehonles terencehonles committed May 15, 2011
Showing with 422 additions and 327 deletions.
  1. +12 −0 ChangeLog.yaml
  2. +2 −2 LICENSE → LICENSE.txt
  3. +0 −3 MANIFEST.in
  4. 0 README → README.txt
  5. +14 −298 progressbar.py → progressbar/__init__.py
  6. +42 −0 progressbar/compat.py
  7. +306 −0 progressbar/widgets.py
  8. +46 −24 setup.py
View
@@ -1,6 +1,18 @@
+2011-05-15:
+ - Removed parse errors for Python2.4 (no, people *should not* be using it
+ but it is only 3 years old and it does not have that many differences)
+
+ - split up progressbar.py into logical units while maintaining backwards
+ compatability
+
+ - Removed MANIFEST.in because it is no longer needed and it was causing
+ distribute to show warnings
+
+
2011-05-14:
- Changes to directory structure so pip can install from Google Code
- Python 3.x related fixes (all examples work on Python 3.1.3)
+ - Added counters, timers, and action bars for iterators with unknown length
2010-08-29:
- Refactored some code and made it possible to use a ProgressBar as
@@ -3,7 +3,7 @@ GNU LGPL license or BSD license (or both).
---
-progressbar - Text progressbar library for python.
+progressbar - Text progress bar library for python.
Copyright (C) 2005 Nilton Volpato
This library is free software; you can redistribute it and/or
@@ -22,7 +22,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
---
-progressbar - Text progressbar library for python
+progressbar - Text progress bar library for python
Copyright (c) 2008 Nilton Volpato
All rights reserved.
View
@@ -1,3 +0,0 @@
-include README MANIFEST MANIFEST.in LICENSE
-include setup.py
-include progressbar.py
File renamed without changes.
@@ -42,14 +42,11 @@
from __future__ import division
-__author__ = 'Nilton Volpato'
-__author_email__ = 'first-name dot last-name @ gmail.com'
-__date__ = '2011-05-14'
-__version__ = '2.3'
-
-import datetime
import math
-import sys, time, os
+import os
+import signal
+import sys
+import time
try:
from fcntl import ioctl
@@ -58,300 +55,19 @@
except ImportError:
pass
-import signal
-
-# Python 3.x (and backports) use a modified iterator syntax
-# This will allow 2.x to behave with 3.x iterators
-if not hasattr(__builtins__, 'next'):
- def next(iter):
- try:
- # Try new style iterators
- return iter.__next__()
- except AttributeError:
- # Fallback in case of a "native" iterator
- return iter.next()
-
-# Python 3.x int is practically synonymous for a long in 2.x so create an alias
-if not hasattr(__builtins__, 'long'): long = int
-
+from progressbar.compat import *
+from progressbar.widgets import *
-def noop_decorator(fn): return fn
-
-try: from abc import ABCMeta, abstractmethod
-except ImportError:
- ABCMeta = None
- abstractmethod = noop_decorator
+__author__ = 'Nilton Volpato'
+__author_email__ = 'first-name dot last-name @ gmail.com'
+__date__ = '2011-05-14'
+__version__ = '2.3'
-def format_updatable(updatable, pbar):
- if hasattr(updatable, 'update'): return updatable.update(pbar)
- else: return updatable
class UnknownLength: pass
-class ProgressBarWidget(object):
- '''The base class for all widgets
-
- The ProgressBar will call the widget's update value when the widget should
- be updated. The widget's size may change between calls, but the widget may
- display incorrectly if the size changes drastically and repeatedly.
-
- The boolean TIME_SENSITIVE informs the ProgressBar that it should be
- updated more often because it is time sensitive.
- '''
- if ABCMeta is not None: __metaclass__ = ABCMeta
-
- TIME_SENSITIVE = False
- __slots__ = ()
-
- @abstractmethod
- def update(self, pbar):
- '''Updates the widget.
-
- pbar - a reference to the calling ProgressBar
- '''
-
-
-class ProgressBarWidgetHFill(ProgressBarWidget):
- '''The base class for all variable width widgets.
-
- This widget is much like the \\hfill command in TeX, it will expand to
- fill the line. You can use more than one in the same line, and they will
- all have the same width, and together will fill the line.
- '''
-
- @abstractmethod
- def update(self, pbar, width):
- '''Updates the widget providing the total width the widget must fill.
-
- pbar - a reference to the calling ProgressBar
- width - The total width the widget must fill
- '''
-
-
-class Timer(ProgressBarWidget):
- 'Widget which displays the elapsed seconds.'
-
- __slots__ = ('format',)
- TIME_SENSITIVE = True
-
- def __init__(self, format='Elapsed Time: %s'):
- self.format = format
-
- @staticmethod
- def format_time(seconds):
- 'Formats time as the string "HH:MM:SS".'
-
- return str(datetime.timedelta(seconds=int(seconds)))
-
-
- def update(self, pbar):
- 'Updates the widget to show the elapsed time.'
-
- return self.format % self.format_time(pbar.seconds_elapsed)
-
-
-class ETA(Timer):
- 'Widget which attempts to estimate the time of arrival.'
-
- TIME_SENSITIVE = True
-
- def update(self, pbar):
- 'Updates the widget to show the ETA or total time when finished.'
-
- if pbar.currval == 0:
- return 'ETA: --:--:--'
- elif pbar.finished:
- return 'Time: %s' % self.format_time(pbar.seconds_elapsed)
- else:
- elapsed = pbar.seconds_elapsed
- eta = elapsed * pbar.maxval / pbar.currval - elapsed
- return 'ETA: %s' % self.format_time(eta)
-
-
-class FileTransferSpeed(ProgressBarWidget):
- 'Widget for showing the transfer speed (useful for file transfers).'
-
- format = '%6.2f %s%s/s'
- prefixes = ' kMGTPEZY'
- __slots__ = ('unit', 'format')
-
- def __init__(self, unit='B'):
- self.unit = unit
-
- def update(self, pbar):
- 'Updates the widget with the current SI prefixed speed.'
-
- if pbar.seconds_elapsed < 2e-6 or pbar.currval < 2e-6: # =~ 0
- scaled = power = 0
- else:
- speed = pbar.currval / pbar.seconds_elapsed
- power = int(math.log(speed, 1000))
- scaled = speed / 1000.**power
-
- return self.format % (scaled, self.prefixes[power], self.unit)
-
-
-class AnimatedMarker(ProgressBarWidget):
- '''An animated marker for the progress bar which defaults to appear as if
- it were rotating.
- '''
-
- __slots__ = ('markers', 'curmark')
-
- def __init__(self, markers='|/-\\'):
- self.markers = markers
- self.curmark = -1
-
- def update(self, pbar):
- '''Updates the widget to show the next marker or the first marker when
- finished'''
-
- if pbar.finished: return self.markers[0]
-
- self.curmark = (self.curmark + 1) % len(self.markers)
- return self.markers[self.curmark]
-
-# Alias for backwards compatibility
-RotatingMarker = AnimatedMarker
-
-
-class Counter(ProgressBarWidget):
- 'Displays the current count'
-
- __slots__ = ('format',)
-
- def __init__(self, format='%d'):
- self.format = format
-
- def update(self, pbar):
- return self.format % pbar.currval
-
-
-class Percentage(ProgressBarWidget):
- 'Displays the current percentage as a number with a percent sign.'
-
- def update(self, pbar):
- return '%3d%%' % pbar.percentage()
-
-
-class FormatLabel(Timer):
- 'Displays a formatted label'
-
- mapping = {
- 'elapsed': ('seconds_elapsed', Timer.format_time),
- 'finished': ('finished', None),
- 'last_update': ('last_update_time', None),
- 'max': ('maxval', None),
- 'seconds': ('seconds_elapsed', None),
- 'start': ('start_time', None),
- 'value': ('currval', None)
- }
-
- __slots__ = ('format',)
- def __init__(self, format): self.format = format
-
- def update(self, pbar):
- context = {}
- for name, (key, transform) in self.mapping.items():
- try:
- value = getattr(pbar, key)
- context[name] = value if transform is None else transform(value)
- except: pass
-
- return self.format % context
-
-
-class SimpleProgress(ProgressBarWidget):
- 'Returns progress as a count of the total (e.g.: "5 of 47")'
-
- __slots__ = ('sep',)
-
- def __init__(self, sep=' of '):
- self.sep = sep
-
- def update(self, pbar):
- return '%d%s%d' % (pbar.currval, self.sep, pbar.maxval)
-
-
-class Bar(ProgressBarWidgetHFill):
- 'A progress bar which stretches to fill the line.'
-
- __slots__ = ('marker', 'left', 'right', 'fill', 'fill_left')
-
- def __init__(self, marker='#', left='|', right='|', fill=' ',
- fill_left=True):
- '''Creates a customizable progress bar.
-
- marker - string or updatable object to use as a marker
- left - string or updatable object to use as a left border
- right - string or updatable object to use as a right border
- fill - character to use for the empty part of the progress bar
- fill_left - whether to fill from the left or the right
- '''
- self.marker = marker
- self.left = left
- self.right = right
- self.fill = fill
- self.fill_left = fill_left
-
- def update(self, pbar, width):
- 'Updates the progress bar and its subcomponents'
-
- left, marker, right = (format_updatable(i, pbar) for i in
- (self.left, self.marker, self.right))
-
- width -= len(left) + len(right)
- # Marker must *always* have length of 1
- marker *= int(pbar.currval / pbar.maxval * width)
-
- if self.fill_left:
- return '%s%s%s' % (left, marker.ljust(width, self.fill), right)
- else:
- return '%s%s%s' % (left, marker.rjust(width, self.fill), right)
-
-
-class ReverseBar(Bar):
- def __init__(self, marker='#', left='|', right='|', fill=' ',
- fill_left=False):
- '''Creates a customizable progress bar.
-
- marker - string or updatable object to use as a marker
- left - string or updatable object to use as a left border
- right - string or updatable object to use as a right border
- fill - character to use for the empty part of the progress bar
- fill_left - whether to fill from the left or the right
- '''
- self.marker = marker
- self.left = left
- self.right = right
- self.fill = fill
- self.fill_left = fill_left
-
-
-class BouncingBar(Bar):
- def update(self, pbar, width):
- 'Updates the progress bar and its subcomponents'
-
- left, marker, right = (format_updatable(i, pbar) for i in
- (self.left, self.marker, self.right))
-
- width -= len(left) + len(right)
-
- if pbar.finished: return '%s%s%s' % (left, width * marker, right)
-
- position = int(pbar.currval % (width * 2 - 1))
- if position > width: position = width * 2 - position
- lpad = self.fill * (position - 1)
- rpad = self.fill * (width - len(marker) - len(lpad))
-
- # Swap if we want to bounce the other way
- if not self.fill_left: rpad, lpad = lpad, rpad
-
- return '%s%s%s%s%s' % (left, lpad, marker, rpad, right)
-
-
class ProgressBar(object):
'''The ProgressBar class which updates and prints the bar.
@@ -500,7 +216,7 @@ def _format_widgets(self):
width = self.term_width
for index, widget in enumerate(self.widgets):
- if isinstance(widget, ProgressBarWidgetHFill):
+ if isinstance(widget, WidgetHFill):
result.append(widget)
expanding.insert(0, index)
else:
@@ -545,10 +261,10 @@ def _update_widgets(self):
for w in self.widgets)
- def update(self, value):
+ def update(self, value=None):
'Updates the ProgressBar to a new value.'
- if value is not None:
+ if value is not None and value is not UnknownLength:
if (self.maxval is not UnknownLength
and not 0 <= value <= self.maxval):
@@ -601,7 +317,7 @@ def finish(self):
'Puts the ProgressBar bar in the finished state.'
self.finished = True
- self.update(self.maxval if self.maxval is not UnknownLength else None)
+ self.update(self.maxval)
self.fd.write('\n')
if self.signal_set:
signal.signal(signal.SIGWINCH, signal.SIG_DFL)
Oops, something went wrong. Retry.

0 comments on commit 06acded

Please sign in to comment.