def _mapped_dependencies(self, jardepmap, binary, confs): # TODO(John Sirois): rework product mapping towards well known types # Generate a map of jars for each unique artifact (org, name) externaljars = OrderedDict() visited = set() for conf in confs: mapped = jardepmap.get((binary, conf)) if mapped: for basedir, jars in mapped.items(): for externaljar in jars: if (basedir, externaljar) not in visited: visited.add((basedir, externaljar)) keys = jardepmap.keys_for(basedir, externaljar) for key in keys: if isinstance(key, tuple) and len(key) == 3: org, name, configuration = key classpath_entry = externaljars.get( (org, name)) if not classpath_entry: classpath_entry = {} externaljars[(org, name)] = classpath_entry classpath_entry[conf] = os.path.join( basedir, externaljar) return externaljars.values()
def _record(self, goal, elapsed): phase = Phase.of(goal) phase_timings = self._timings.get(phase) if phase_timings is None: phase_timings = OrderedDict(()) self._timings[phase] = phase_timings goal_timings = phase_timings.get(goal) if goal_timings is None: goal_timings = [] phase_timings[goal] = goal_timings goal_timings.append(elapsed)
def _mapped_dependencies(self, jardepmap, binary, confs): # TODO(John Sirois): rework product mapping towards well known types # Generate a map of jars for each unique artifact (org, name) externaljars = OrderedDict() visited = set() for conf in confs: mapped = jardepmap.get((binary, conf)) if mapped: for basedir, jars in mapped.items(): for externaljar in jars: if (basedir, externaljar) not in visited: visited.add((basedir, externaljar)) keys = jardepmap.keys_for(basedir, externaljar) for key in keys: if isinstance(key, tuple) and len(key) == 3: org, name, configuration = key classpath_entry = externaljars.get((org, name)) if not classpath_entry: classpath_entry = {} externaljars[(org, name)] = classpath_entry classpath_entry[conf] = os.path.join(basedir, externaljar) return externaljars.values()
class Timer(object): """Provides timing support for goal execution.""" @classmethod @contextmanager def begin(cls, timer=None): """Begins a new ``Timer`` and yields it in a with context. The timer will be finished if not already by the block yielded to. """ t = Timer(timer) try: yield t finally: t.finish() def __init__(self, timer=None): """Creates a timer that uses time.time for timing intervals by default. :param timer: A callable that returns the current time in fractional seconds. """ self._now = timer or time.time if not(callable(self._now)): # TODO(John Sirois): `def jake(bob): pass` is also callable - we want a no-args callable - # create a better check. raise ValueError('Timer must be a callable object.') self._timings = OrderedDict() self._elapsed = None self._start = self._now() def finish(self): """Finishes this timer if not already finished. Calls to ``timed`` after this will raise a ValueError since the timing window is complete. """ if self._elapsed is None: self._elapsed = self._now() - self._start @property def timings(self): """Returns the phase timings as an ordered mapping from the ``Phase`` objects executed to ordered mappings of the ``Goal`` objects executed in the phase to the list of timings corresponding to each execution of the goal. Note that the list of timings will be singleton for all goals except those participating in a ``Group``. Grouped goals will have or more timings in the list corresponding to each chunk of targets the goal executed against when iterating the group. """ return self._timings @property def elapsed(self): """Returns the total elapsed time in fractional seconds from the creation of this timer until it was ``finished``. """ if self._elapsed is None: raise ValueError('Timer has not been finished yet.') return self._elapsed @contextmanager def timed(self, goal): """Records the time taken to execute the yielded block an records this timing against the given goal's total runtime. """ if self._elapsed is not None: raise ValueError('This timer is already finished.') start = self._now() try: yield finally: self._record(goal, self._now() - start) def _record(self, goal, elapsed): phase = Phase.of(goal) phase_timings = self._timings.get(phase) if phase_timings is None: phase_timings = OrderedDict(()) self._timings[phase] = phase_timings goal_timings = phase_timings.get(goal) if goal_timings is None: goal_timings = [] phase_timings[goal] = goal_timings goal_timings.append(elapsed) def render_timing_report(self): """Renders this timer's timings into the classic pants timing report format.""" report = ('Timing report\n' '=============\n') for phase, timings in self.timings.items(): phase_time = None for goal, times in timings.items(): if len(times) > 1: report += '[%(phase)s:%(goal)s(%(numsteps)d)] %(timings)s -> %(total).3fs\n' % { 'phase': phase.name, 'goal': goal.name, 'numsteps': len(times), 'timings': ','.join('%.3fs' % t for t in times), 'total': sum(times) } else: report += '[%(phase)s:%(goal)s] %(total).3fs\n' % { 'phase': phase.name, 'goal': goal.name, 'total': sum(times) } if not phase_time: phase_time = 0 phase_time += sum(times) if len(timings) > 1: report += '[%(phase)s] total: %(total).3fs\n' % { 'phase': phase.name, 'total': phase_time } report += 'total: %.3fs' % self.elapsed return report