def info_single(self, message, overwrite_verbose=False, mc='yellow', nl_before=0, nl_after=0, cut_after=80, level=1, progress=None): if isinstance(message, str): message = remove_spaces(message) if level not in self.single_line_prefixes: raise TerminalError( "the `info_single` function does not know how to deal with a level of %d :/" % level) if cut_after: message_line = c( "%s%s\n" % (self.single_line_prefixes[level], textwrap.fill(str(message), cut_after)), mc) else: message_line = c( "%s%s\n" % (self.single_line_prefixes[level], str(message)), mc) message_line = ('\n' * nl_before) + message_line + ('\n' * nl_after) if progress: progress.clear() self.write(message_line, overwrite_verbose=False) progress.update(progress.msg) else: self.write(message_line, overwrite_verbose=False)
def make_checkpoint(self, checkpoint_key=None, increment_to=None): if not checkpoint_key: checkpoint_key = self.num_checkpoints + 1 if checkpoint_key in self.checkpoints: raise TerminalError( 'Timer.make_checkpoint :: %s already exists as a checkpoint key. ' 'All keys must be unique' % (str(checkpoint_key))) checkpoint = self.timestamp() self.checkpoints[checkpoint_key] = checkpoint self.last_checkpoint_key = checkpoint_key self.num_checkpoints += 1 if increment_to: self.score = increment_to else: self.score += 1 self.scores[checkpoint_key] = self.score if self.required_completion_score and self.score >= self.required_completion_score: self.complete = True return checkpoint
def step_start(self, step, symbol="⚙ "): if not self.pid: raise TerminalError("You don't have an active progress to do it :/") if not self.current: raise TerminalError("You don't have a current progress bad :(") if self.step: raise TerminalError("You already have an unfinished step :( Here it is: '%s'." % self.step) if not self.verbose: return self.step = " / %s " % (step) self.write(self.current + self.step + symbol, dont_update_current=True)
def measure(self): if self.t is None: raise TerminalError("TrackMemory :: You must start the tracker with self.start()") if self.t.timedelta_to_checkpoint(self.t.timestamp(), self.t.last_checkpoint_key) < datetime.timedelta(seconds = self.at_most_every): return False self.t.make_checkpoint(increment_to=self._get_mem()) return True
def update(self, msg): if not self.verbose: return if not self.pid: raise TerminalError('Progress with null pid will not update for msg "%s"' % msg) self.clear() self.write('\r[%s] %s' % (self.pid, msg))
def step_end(self, symbol="👍"): if not self.step: raise TerminalError("You don't have an ongoing step :(") if not self.verbose: return self.write(self.current + self.step + symbol) self.step = None
def new(self, pid): if self.pid: raise TerminalError("Progress.new() can't be called before ending the previous one (Existing: '%s', Competing: '%s')." % (self.pid, pid)) if not self.verbose: return self.pid = '%s %s' % (get_date(), pid) self.get_terminal_width() self.currently_shown = None
def update(self, msg, increment=False): self.msg = msg if not self.verbose: return if not self.pid: raise TerminalError('Progress with null pid will not update for msg "%s"' % msg) if increment: self.increment() self.clear() self.write('\r[%s] %s' % (self.pid, msg))
def new(self, pid, discard_previous_if_exists=False, progress_total_items=None): if self.pid: if discard_previous_if_exists: self.end() else: raise TerminalError("Progress.new() can't be called before ending the previous one (Existing: '%s', Competing: '%s')." % (self.pid, pid)) if not self.verbose: return self.pid = '%s %s' % (get_date(), pid) self.get_terminal_width() self.current = None self.step = None self.progress_total_items = progress_total_items self.progress_current_item = 0 self.t = Timer(self.progress_total_items)
def format_time(self, timedelta, fmt='{hours}:{minutes}:{seconds}', zero_padding=2): """Formats time Examples of `fmt`. Suppose the timedelta is seconds = 1, minutes = 1, hours = 1. {hours}h {minutes}m {seconds}s --> 01h 01m 01s {seconds} seconds --> 3661 seconds {weeks} weeks {minutes} minutes --> 0 weeks 61 minutes {hours}h {seconds}s --> 1h 61s """ unit_hierarchy = ['seconds', 'minutes', 'hours', 'days', 'weeks'] unit_denominations = { 'weeks': 7, 'days': 24, 'hours': 60, 'minutes': 60, 'seconds': 1 } if not fmt: # use the highest two non-zero units, e.g. if it is 7200s, use {hours}h{minutes}m seconds = int(timedelta.total_seconds()) if seconds < 60: fmt = '{seconds}s' else: m = 1 for i, unit in enumerate(unit_hierarchy): if not seconds // (m * unit_denominations[unit]) >= 1: fmt = '{%s}%s{%s}%s' % ( unit_hierarchy[i - 1], unit_hierarchy[i - 1][0], unit_hierarchy[i - 2], unit_hierarchy[i - 2][0]) break elif unit == unit_hierarchy[-1]: fmt = '{%s}%s{%s}%s' % ( unit_hierarchy[i], unit_hierarchy[i][0], unit_hierarchy[i - 1], unit_hierarchy[i - 1][0]) break else: m *= unit_denominations[unit] # parse units present in fmt format_order = [] for i, x in enumerate(fmt): if x == '{': for j, k in enumerate(fmt[i:]): if k == '}': unit = fmt[i + 1:i + j] format_order.append(unit) break if not format_order: raise TerminalError( 'Timer.format_time :: fmt = \'%s\' contains no time units.' % (fmt)) for unit in format_order: if unit not in unit_hierarchy: raise TerminalError('Timer.format_time :: \'%s\' is not a valid unit. Use any of %s.'\ % (unit, ', '.join(unit_hierarchy))) # calculate the value for each unit (e.g. 'seconds', 'days', etc) found in fmt format_values_dict = {} smallest_unit = unit_hierarchy[[ unit in format_order for unit in unit_hierarchy ].index(True)] units_less_than_or_equal_to_smallest_unit = unit_hierarchy[::-1][ unit_hierarchy[::-1].index(smallest_unit):] seconds_in_base_unit = 1 for a in [ v for k, v in unit_denominations.items() if k in units_less_than_or_equal_to_smallest_unit ]: seconds_in_base_unit *= a r = int(timedelta.total_seconds()) // seconds_in_base_unit for i, lower_unit in enumerate(unit_hierarchy): if lower_unit in format_order: m = 1 for upper_unit in unit_hierarchy[i + 1:]: m *= unit_denominations[upper_unit] if upper_unit in format_order: format_values_dict[upper_unit], format_values_dict[ lower_unit] = divmod(r, m) break else: format_values_dict[lower_unit] = r break r = format_values_dict[upper_unit] format_values = [format_values_dict[unit] for unit in format_order] style_str = '0' + str(zero_padding) if zero_padding else '' for unit in format_order: fmt = fmt.replace('{%s}' % unit, '%' + '%s' % (style_str) + 'd') formatted_time = fmt % ( *[format_value for format_value in format_values], ) return formatted_time