def _calculate_values(self, tree, bar_d): """Calculate values for drawing bars of non-leafs in ``tree`` Recurses through ``tree``, replaces ``dict``s with ``(BarDescriptor, dict)`` so ``ProgressTree._draw`` can use the ``BarDescriptor``s to draw the tree """ if all([isinstance(tree, dict), type(tree) != BarDescriptor]): # Calculate value and max_value max_val = 0 value = 0 for k in tree: # Get descriptor by recursing bar_desc = self._calculate_values(tree[k], bar_d) # Reassign to tuple of (new descriptor, tree below) tree[k] = (bar_desc, tree[k]) value += bar_desc["value"].value max_val += bar_desc.get("kwargs", {}).get("max_value", 100) # Merge in values from ``bar_d`` before returning descriptor kwargs = merge_dicts( [bar_d.get("kwargs", {}), dict(max_value=max_val)], deepcopy=True) ret_d = merge_dicts( [bar_d, dict(value=Value(floor(value)), kwargs=kwargs)], deepcopy=True) return BarDescriptor(ret_d) elif isinstance(tree, BarDescriptor): return tree else: raise TypeError("Unexpected type {}".format(type(tree)))
def max_width(self): """Get maximum width of progress bar :rtype: int :returns: Maximum column width of progress bar """ value, unit = float(self._width_str[:-1]), self._width_str[-1] ensure(unit in ["c", "%"], ValueError, "Width unit must be either 'c' or '%'") if unit == "c": ensure(value <= self.columns, ValueError, "Terminal only has {} columns, cannot draw " "bar of size {}.".format(self.columns, value)) retval = value else: # unit == "%" ensure(0 < value <= 100, ValueError, "value=={} does not satisfy 0 < value <= 100".format(value)) dec = value / 100 retval = dec * self.columns return floor(retval)
def _calculate_values(self, tree, bar_d): """Calculate values for drawing bars of non-leafs in ``tree`` Recurses through ``tree``, replaces ``dict``s with ``(BarDescriptor, dict)`` so ``ProgressTree._draw`` can use the ``BarDescriptor``s to draw the tree """ if all([ isinstance(tree, dict), type(tree) != BarDescriptor ]): # Calculate value and max_value max_val = 0 value = 0 for k in tree: # Get descriptor by recursing bar_desc = self._calculate_values(tree[k], bar_d) # Reassign to tuple of (new descriptor, tree below) tree[k] = (bar_desc, tree[k]) value += bar_desc["value"].value max_val += bar_desc.get("kwargs", {}).get("max_value", 100) # Merge in values from ``bar_d`` before returning descriptor kwargs = merge_dicts( [bar_d.get("kwargs", {}), dict(max_value=max_val)], deepcopy=True ) ret_d = merge_dicts( [bar_d, dict(value=Value(floor(value)), kwargs=kwargs)], deepcopy=True ) return BarDescriptor(ret_d) elif isinstance(tree, BarDescriptor): return tree else: raise TypeError("Unexpected type {}".format(type(tree)))
def max_width(self): """Get maximum width of progress bar :rtype: int :returns: Maximum column width of progress bar """ value, unit = float(self._width_str[:-1]), self._width_str[-1] ensure(unit in ["c", "%"], ValueError, "Width unit must be either 'c' or '%'") if unit == "c": ensure( value <= self.columns, ValueError, "Terminal only has {} columns, cannot draw " "bar of size {}.".format(self.columns, value)) retval = value else: # unit == "%" ensure(0 < value <= 100, ValueError, "value=={} does not satisfy 0 < value <= 100".format(value)) dec = value / 100 retval = dec * self.columns return floor(retval)
def draw(self, value, newline=True, flush=True): """Draw the progress bar :type value: int :param value: Progress value relative to ``self.max_value`` :type newline: bool :param newline: If this is set, a newline will be written after drawing """ # This is essentially winch-handling without having # to do winch-handling; cleanly redrawing on winch is difficult # and out of the intended scope of this class; we *can* # however, adjust the next draw to be proper by re-measuring # the terminal since the code is mostly written dynamically # and many attributes and dynamically calculated properties. self._measure_terminal() amount_complete = value / self.max_value fill_amount = int(floor(amount_complete * self.max_width)) empty_amount = self.max_width - fill_amount # e.g., '10/20' if 'fraction' or '50%' if 'percentage' amount_complete_str = ( u"{}/{}".format(value, self.max_value) if self._num_rep == "fraction" else u"{}%".format(int(floor(amount_complete * 100))) ) # Write title if supposed to be above if self._title_pos == "above": title_str = u"{}{}\n".format( " " * self._indent, self.title, ) self._write(title_str, ignore_overflow=True) # Construct just the progress bar bar_str = u''.join([ u(self.filled(self._filled_char * fill_amount)), u(self.empty(self._empty_char * empty_amount)), ]) # Wrap with start and end character bar_str = u"{}{}{}".format(self.start_char, bar_str, self.end_char) # Add on title if supposed to be on left or right if self._title_pos == "left": bar_str = u"{} {}".format(self.title, bar_str) elif self._title_pos == "right": bar_str = u"{} {}".format(bar_str, self.title) # Add indent bar_str = u''.join([" " * self._indent, bar_str]) # Add complete percentage or fraction bar_str = u"{} {}".format(bar_str, amount_complete_str) # Set back to normal after printing bar_str = u"{}{}".format(bar_str, self.term.normal) # Finally, write the completed bar_str self._write(bar_str, s_length=self.full_line_width) # Write title if supposed to be below if self._title_pos == "below": title_str = u"\n{}{}".format( " " * self._indent, self.title, ) self._write(title_str, ignore_overflow=True) # Newline to wrap up if newline: self.cursor.newline() if flush: self.cursor.flush()
def draw(self, value, newline=True, flush=True): """Draw the progress bar :type value: int :param value: Progress value relative to ``self.max_value`` :type newline: bool :param newline: If this is set, a newline will be written after drawing """ # This is essentially winch-handling without having # to do winch-handling; cleanly redrawing on winch is difficult # and out of the intended scope of this class; we *can* # however, adjust the next draw to be proper by re-measuring # the terminal since the code is mostly written dynamically # and many attributes and dynamically calculated properties. self._measure_terminal() amount_complete = value / self.max_value fill_amount = int(floor(amount_complete * self.max_width)) empty_amount = self.max_width - fill_amount # e.g., '10/20' if 'fraction' or '50%' if 'percentage' amount_complete_str = (u"{}/{}".format(value, self.max_value) if self._num_rep == "fraction" else u"{}%".format( int(floor(amount_complete * 100)))) # Write title if supposed to be above if self._title_pos == "above": title_str = u"{}{}\n".format( " " * self._indent, self.title, ) self._write(title_str, ignore_overflow=True) # Construct just the progress bar bar_str = u''.join([ u(self.filled(self._filled_char * fill_amount)), u(self.empty(self._empty_char * empty_amount)), ]) # Wrap with start and end character bar_str = u"{}{}{}".format(self.start_char, bar_str, self.end_char) # Add on title if supposed to be on left or right if self._title_pos == "left": bar_str = u"{} {}".format(self.title, bar_str) elif self._title_pos == "right": bar_str = u"{} {}".format(bar_str, self.title) # Add indent bar_str = u''.join([" " * self._indent, bar_str]) # Add complete percentage or fraction bar_str = u"{} {}".format(bar_str, amount_complete_str) # Set back to normal after printing bar_str = u"{}{}".format(bar_str, self.term.normal) # Finally, write the completed bar_str self._write(bar_str, s_length=self.full_line_width) # Write title if supposed to be below if self._title_pos == "below": title_str = u"\n{}{}".format( " " * self._indent, self.title, ) self._write(title_str, ignore_overflow=True) # Newline to wrap up if newline: self.cursor.newline() if flush: self.cursor.flush()
def value(self, val): self._value = floor(val)