Exemple #1
0
    def format(self, width=None, elapsed=None):
        """
        Args:
            width (int): Width in columns to make progress bar
            elapsed(float): Time since started. Automatically determined if :py:data:`None`

        Returns:
            :py:class:`str`: Formatted progress bar or counter

        Format progress bar or counter
        """

        width = width or self.manager.width
        total = self.total

        iterations = float(abs(self.count - self.start_count))

        fields = self.fields.copy()
        fields.update(self._fields)

        # Warn on reserved fields
        reserved_fields = set(fields) & RESERVED_FIELDS | {
            match.group()
            for match in (RE_SUBCOUNTER_FIELDS.match(key) for key in fields)
            if match
        }

        if reserved_fields:
            warn_best_level('Ignoring reserved fields specified as user-defined fields: %s' %
                            ', '.join(reserved_fields),
                            EnlightenWarning)

        force_float = isinstance(self.count, float) or isinstance(total, float)
        fields['count'] = Float(self.count) if force_float else self.count
        fields['desc'] = self.desc or u''
        fields['total'] = Float(total) if force_float and total is not None else total
        fields['unit'] = self.unit or u''
        fields['desc_pad'] = u' ' if self.desc else u''
        fields['unit_pad'] = u' ' if self.unit else u''

        # Get elapsed time
        if elapsed is None:
            elapsed = self.elapsed

        fields['elapsed'] = format_time(elapsed)

        # Get rate. Elapsed could be 0 if counter was not updated and has a zero total.
        rate = Float(iterations / elapsed) if elapsed else Float(0.0)
        fields['rate'] = rate
        fields['interval'] = rate ** -1 if rate else rate

        # Only process bar if total was given and n doesn't exceed total
        if total is not None and self.count <= total:
            return self._format_bar(fields, iterations, width, elapsed, force_float)

        # Otherwise return a counter
        return self._format_counter(fields, width, elapsed, force_float)
Exemple #2
0
    def _get_subcounters(self, elapsed, bar_fields=True):
        """
        Args:
            elapsed(float): Time since started.
            bar_fields(bool): When False, only set fields for basic counter

        Returns:
            :py:class:`tuple`: list of subcounters and dictionary of additional fields

        Each subcounter in the list will be in a tuple of (subcounter, percentage)
        Fields in the dictionary are addressed in the Format documentation of this class

        When `bar_fields` is False, only subcounter count, interval, and rate fields are set.
        percentage will be set to 0.0
        """

        fields = {}
        subcounters = []

        for num, subcounter in enumerate(self._subcounters, 1):

            fields['count_%d' % num] = subcounter.count

            if self.total and bar_fields:
                subPercentage = subcounter.count / float(self.total)
            else:
                subPercentage = 0.0

            if bar_fields:
                fields['percentage_%d' % num] = subPercentage * 100

            # Save in tuple: count, percentage
            subcounters.append((subcounter, subPercentage))

            if subcounter.all_fields:

                interations = float(abs(subcounter.count - subcounter.start_count))

                if elapsed:
                    # Use float to force to float in Python 2
                    rate = fields['rate_%d' % num] = interations / elapsed
                else:
                    rate = fields['rate_%d' % num] = 0.0

                fields['interval_%d' % num] = rate ** -1 if rate else 0.0

                if not bar_fields:
                    continue

                if self.total == 0:
                    fields['eta_%d' % num] = u'00:00'
                elif rate:
                    fields['eta_%d' % num] = format_time((self.total - interations) / rate)
                else:
                    fields['eta_%d' % num] = u'?'

        return subcounters, fields
Exemple #3
0
    def format(self, width=None, elapsed=None):
        """
        Args:
            width (int): Width in columns to make progress bar
            elapsed(float): Time since started. Automatically determined if :py:data:`None`

        Returns:
            :py:class:`str`: Formatted status bar

        Format status bar
        """

        width = width or self.manager.width
        justify = self.justify

        # If static message was given, just return it
        if self._static is not None:
            rtn = self._static

        # If there is no format, return empty
        elif self.status_format is None:
            rtn = ''

        # Generate from format
        else:
            fields = self.fields.copy()
            fields.update(self._fields)

            # Warn on reserved fields
            reserved_fields = (set(fields) & STATUS_FIELDS)
            if reserved_fields:
                warn_best_level(
                    'Ignoring reserved fields specified as user-defined fields: %s'
                    % ', '.join(reserved_fields), EnlightenWarning)

            elapsed = elapsed if elapsed is not None else self.elapsed
            fields['elapsed'] = format_time(elapsed)
            fields['fill'] = u'{0}'

            # Format
            try:
                if FORMAT_MAP_SUPPORT:
                    rtn = self.status_format.format_map(fields)
                else:  # pragma: no cover
                    rtn = self.status_format.format(**fields)
            except KeyError as e:
                raise_from_none(
                    ValueError('%r specified in format, but not provided' %
                               e.args[0]))

        rtn = self._fill_text(rtn, width)

        return self._colorize(justify(rtn, width=width, fillchar=self.fill))
Exemple #4
0
    def format(self, width=None, elapsed=None):
        """
        Args:
            width (int): Width in columns to make progress bar
            elapsed(float): Time since started. Automatically determined if :py:data:`None`

        Returns:
            :py:class:`str`: Formatted status bar

        Format status bar
        """

        width = width or self.manager.width
        justify = self.justify

        # If static message was given, just return it
        if self._static is not None:
            rtn = self._static

        # If there is no format, return empty
        elif self.status_format is None:
            rtn = ''

        # Generate from format
        else:
            fields = self.fields.copy()
            fields.update(self._fields)
            elapsed = elapsed if elapsed is not None else self.elapsed
            fields['elapsed'] = format_time(elapsed)
            fields['fill'] = u'{0}'

            # Format
            try:
                rtn = self.status_format.format(**fields)
            except KeyError as e:
                raise ValueError('%r specified in format, but not provided' %
                                 e.args[0])

        rtn = self._fill_text(rtn, width)

        return self._colorize(justify(rtn, width=width, fillchar=self.fill))
Exemple #5
0
    def _format_bar(self, fields, iterations, width, elapsed, force_float):
        """
        Args:
            fields (dict): Initial set of formatting fields
            iterations (float): Absolute value of count change from start
            width (int): Width in columns to make progress bar
            elapsed(float): Time since started

        Returns:
            :py:class:`str`: Formatted progress bar

        Format progress bar
        """

        fields['bar'] = u'{0}'
        fields['len_total'] = len(str(self.total))

        # Get percentage
        if self.total == 0:
            # If total is 0, force to 100 percent
            percentage = 1
            fields['eta'] = u'00:00'
        else:
            # Use float to force to float in Python 2
            percentage = self.count / float(self.total)
            rate = fields['rate']

            # Get eta
            if rate:
                # Use iterations so a counter running backwards is accurate
                fields['eta'] = format_time((self.total - iterations) / rate)
            else:
                fields['eta'] = u'?'

        fields['percentage'] = percentage * 100

        # Have to go through subcounters here so the fields are available
        subcounters = self._get_subcounters(elapsed, fields, force_float=force_float)

        # Partially format
        try:
            if FORMAT_MAP_SUPPORT:
                rtn = self.bar_format.format_map(fields)
            else:  # pragma: no cover
                rtn = self.bar_format.format(**fields)
        except KeyError as e:
            raise_from_none(ValueError(self._get_format_error(e.args[0])))

        # Determine bar width
        if self.offset is None:
            barWidth = width - self.manager.term.length(rtn) + 3  # 3 is for the bar placeholder
        else:
            # Offset was explicitly given
            barWidth = width - len(rtn) + self.offset + 3  # 3 is for the bar placeholder

        complete = barWidth * percentage
        barLen = int(complete)
        barText = u''

        if subcounters:
            block_count = [int(barWidth * fields['percentage_0'] / 100)]
            partial_len = (barLen - 1) if fields['count_0'] else barLen
            remaining = []

            # Get full blocks for subcounters and preserve remainders
            for idx, entry in enumerate(subcounters, 1):
                remainder, count = math.modf(barWidth * entry[1])
                block_count.append(int(count))
                remaining.append((remainder, idx))

            # Until blocks are accounted for, add full blocks for highest remainders
            remaining.sort()
            while sum(block_count) < partial_len and remaining:
                block_count[remaining.pop()[1]] += 1

            # Format partial bars
            for idx, subLen in reversed(list(enumerate(block_count))):
                if idx:
                    subcounter = subcounters[idx - 1][0]
                    # pylint: disable=protected-access
                    barText += subcounter._colorize(self.series[-1] * subLen)
                else:
                    # Get main partial bar
                    barText += self.series[-1] * subLen

            partial_len = sum(block_count)

        else:
            # Get main partial bar
            barText += self.series[-1] * barLen
            partial_len = barLen

        # If bar isn't complete, add partial block and fill
        if barLen < barWidth:
            if fields.get('count_0', self.count):
                barText += self.series[int(round((complete - barLen) * (len(self.series) - 1)))]
                partial_len += 1
            barText += self.series[0] * (barWidth - partial_len)

        return rtn.format(self._colorize(barText))
Exemple #6
0
    def _get_subcounters(self, elapsed, fields, bar_fields=True, force_float=False):
        """
        Args:
            elapsed(float): Time since started.
            bar_fields(bool): When False, only set fields for basic counter

        Returns:
            :py:class:`tuple`: list of subcounters and dictionary of additional fields

        Each subcounter in the list will be in a tuple of (subcounter, percentage)
        Fields in the dictionary are addressed in the Format documentation of this class

        When `bar_fields` is False, only subcounter count, interval, and rate fields are set.
        percentage will be set to 0.0
        """

        subcounters = []
        count_00 = 0
        start_count_00 = 0

        if not self._subcounters:
            return subcounters

        for num, subcounter in enumerate(self._subcounters, 1):

            count = subcounter.count
            count_00 += count
            start_count_00 += subcounter.start_count

            fields['count_%d' % num] = Float(count) if force_float else count

            if self.total and bar_fields:
                subPercentage = count / float(self.total)
            else:
                subPercentage = 0.0

            if bar_fields:
                fields['percentage_%d' % num] = subPercentage * 100

            # Save in tuple: count, percentage
            subcounters.append((subcounter, subPercentage))

            if not subcounter.all_fields:
                continue

            # Explicit conversion to float required for Python 2
            interations = float(abs(count - subcounter.start_count))
            rate = Float(interations / elapsed) if elapsed else Float(0.0)
            fields['rate_%d' % num] = rate
            fields['interval_%d' % num] = rate ** -1 if rate else rate

            if not bar_fields:
                continue

            if self.total == 0:
                fields['eta_%d' % num] = u'00:00'
            elif rate:
                fields['eta_%d' % num] = format_time((self.total - interations) / rate)
            else:
                fields['eta_%d' % num] = u'?'

        # Percentage_0 and percentage_00, bar_format only
        if bar_fields:
            fields['percentage_00'] = percentage_00 = sum(sub[1] for sub in subcounters) * 100
            fields['percentage_0'] = fields['percentage'] - percentage_00

        # count_00 fields (Sum of subcounters)
        fields['count_00'] = Float(count_00) if force_float else count_00
        rate = Float(float(abs(count_00 - start_count_00)) / elapsed) if elapsed else Float(0.0)
        fields['rate_00'] = rate
        fields['interval_00'] = rate ** -1 if rate else rate

        # count_0 fields (Excluding subcounters)
        count_0 = fields['count_0'] = fields['count'] - count_00
        start_count_0 = self.start_count - start_count_00
        rate = Float(float(abs(count_0 - start_count_0)) / elapsed) if elapsed else Float(0.0)
        fields['rate_0'] = rate
        fields['interval_0'] = rate ** -1 if rate else rate

        return subcounters
Exemple #7
0
    def test_days(self):
        """Verify days formatting"""

        self.assertEqual(format_time(86400), '1d 0h 00:00')
        self.assertEqual(format_time(1447597), '16d 18h 06:37')
Exemple #8
0
    def test_hours(self):
        """Verify hours formatting"""

        self.assertEqual(format_time(3600), '1h 00:00')
        self.assertEqual(format_time(43980), '12h 13:00')
        self.assertEqual(format_time(43998), '12h 13:18')
Exemple #9
0
    def test_minutes(self):
        """Verify minutes formatting"""

        self.assertEqual(format_time(60), '01:00')
        self.assertEqual(format_time(128), '02:08')
        self.assertEqual(format_time(1684), '28:04')
Exemple #10
0
    def test_seconds(self):
        """Verify seconds formatting"""

        self.assertEqual(format_time(0), '00:00')
        self.assertEqual(format_time(6), '00:06')
        self.assertEqual(format_time(42), '00:42')
Exemple #11
0
    def format(self, width=None, elapsed=None):
        """
        Args:
            width (int): Width in columns to make progress bar
            elapsed(float): Time since started. Automatically determined if :py:data:`None`

        Returns:
            :py:class:`str`: Formatted progress bar or counter

        Format progress bar or counter
        """

        width = width or self.manager.width

        iterations = float(abs(self.count - self.start_count))

        fields = self.fields.copy()
        fields.update(self._fields)

        # Warn on reserved fields
        reserved_fields = (set(fields) & COUNTER_FIELDS) | set(
            match.group() for match in (RE_SUBCOUNTER_FIELDS.match(key) for key in fields) if match
        )
        if reserved_fields:
            warn_best_level('Ignoring reserved fields specified as user-defined fields: %s' %
                            ', '.join(reserved_fields),
                            EnlightenWarning)

        fields.update({'bar': u'{0}',
                       'count': self.count,
                       'desc': self.desc or u'',
                       'total': self.total,
                       'unit': self.unit or u'',
                       'desc_pad': u' ' if self.desc else u'',
                       'unit_pad': u' ' if self.unit else u''})

        # Get elapsed time
        if elapsed is None:
            elapsed = self.elapsed

        fields['elapsed'] = format_time(elapsed)

        # Get rate. Elapsed could be 0 if counter was not updated and has a zero total.
        if elapsed:
            # Use iterations so a counter running backwards is accurate
            rate = fields['rate'] = iterations / elapsed
        else:
            rate = fields['rate'] = 0.0

        fields['interval'] = rate ** -1 if rate else 0.0
        # Only process bar if total was given and n doesn't exceed total
        if self.total is not None and self.count <= self.total:

            fields['len_total'] = len(str(self.total))

            # Get percentage
            if self.total == 0:
                # If total is 0, force to 100 percent
                percentage = 1
                fields['eta'] = u'00:00'
            else:
                # Use float to force to float in Python 2
                percentage = self.count / float(self.total)

                # Get eta
                if rate:
                    # Use iterations so a counter running backwards is accurate
                    fields['eta'] = format_time((self.total - iterations) / rate)
                else:
                    fields['eta'] = u'?'

            fields['percentage'] = percentage * 100

            # Have to go through subcounters here so the fields are available
            subcounters, subFields = self._get_subcounters(elapsed)

            # Calculate count and percentage for remainder
            if subcounters:
                fields.update(subFields)
                fields['count_0'] = self.count - sum(sub[0].count for sub in subcounters)
                fields['percentage_0'] = (percentage - sum(sub[1] for sub in subcounters)) * 100

            # Partially format
            try:
                if FORMAT_MAP_SUPPORT:
                    rtn = self.bar_format.format_map(fields)
                else:  # pragma: no cover
                    rtn = self.bar_format.format(**fields)
            except KeyError as e:
                raise_from_none(ValueError('%r specified in format, but not provided' % e.args[0]))

            # Format the bar
            if self.offset is None:
                barWidth = width - self.manager.term.length(rtn) + 3  # 3 is for the bar placeholder
            else:
                # Offset was explicitly given
                barWidth = width - len(rtn) + self.offset + 3  # 3 is for the bar placeholder

            complete = barWidth * percentage
            barLen = int(complete)
            barText = u''
            subOffset = 0

            for subcounter, subPercentage in reversed(subcounters):
                subLen = int(barWidth * subPercentage)
                # pylint: disable=protected-access
                barText += subcounter._colorize(self.series[-1] * subLen)
                subOffset += subLen

            barText += self.series[-1] * (barLen - subOffset)

            if barLen < barWidth:
                barText += self.series[int(round((complete - barLen) * (len(self.series) - 1)))]
                barText += self.series[0] * (barWidth - barLen - 1)

            return rtn.format(self._colorize(barText))

        # Otherwise return a counter

        # Update fields from subcounters
        fields['fill'] = u'{0}'
        subcounters, subFields = self._get_subcounters(elapsed, bar_fields=False)
        if subcounters:
            fields.update(subFields)
            fields['count_0'] = self.count - sum(sub[0].count for sub in subcounters)

        try:
            if FORMAT_MAP_SUPPORT:
                rtn = self.counter_format.format_map(fields)
            else:  # pragma: no cover
                rtn = self.counter_format.format(**fields)
        except KeyError as e:
            raise_from_none(ValueError('%r specified in format, but not provided' % e.args[0]))

        return self._fill_text(rtn, width, offset=self.offset)