def expand(val, level=3): type_index = type_registry[val] result = [cheap_repr(val), type_index] if type_index < type_registry.num_basic_types or level == 0: return result exp = partial(expand, level=level - 1) # noinspection PyBroadException try: length = len(val) except: pass else: result += ['len() = %s' % length] if isinstance(val, (str, bytes, range) if PY3 else (str, unicode, xrange)): return result if isinstance(val, Sequence): if len(val) <= 8: indices = range(len(val)) else: indices = chain(range(3), range(len(val) - 3, len(val))) for i in indices: result += [(str(i), exp(val[i]))] elif isinstance(val, Mapping): for k, v in islice(iteritems(val), 10): result += [(cheap_repr(k), exp(v))] elif isinstance(val, Set): if len(val) <= 8: vals = val else: vals = islice(val, 6) for i, v in enumerate(vals): result += [('<%s>' % i, exp(v))] d = getattr(val, '__dict__', None) if d: for k, v in islice(iteritems(d), 50): if isinstance(v, TracedFile): continue result += [(str(k), exp(v))] else: slots = getattr(val, '__slots__', None) if slots: for s in slots: try: attr = getattr(val, s) except AttributeError: pass else: result += [(str(s), exp(attr))] return result
def enter_call(self, enter_info): frame = enter_info.current_frame if frame.f_code not in self._code_infos: return frame_info = self.stack[frame] frame_info.start_time = datetime.now() frame_info.iteration = Iteration() arg_info = inspect.getargvalues(frame) arg_names = chain(arg_info[0], arg_info[1:3]) f_locals = arg_info[3].copy() arguments = [(name, f_locals.pop(name)) for name in arg_names if name] + list(f_locals.items()) frame_info.arguments = json.dumps([[k, cheap_repr(v)] for k, v in arguments]) self.stack.get(frame.f_back, dummy_namespace).inner_call = frame_info.call_id = self._call_id()
def exit_call(self, exit_info): frame = exit_info.current_frame if frame.f_code not in self._code_infos: return frame_info = self.stack[frame] top_iteration = frame_info.iteration loop_iterations = top_iteration.extract_iterations()['loops'] node_values = _deep_dict() def extract_values(iteration, path): for k, v in iteration.vals.items(): full_path = (k,) + path d = node_values for path_k in full_path[:-1]: d = d[path_k] d[full_path[-1]] = v for loop in iteration.loops.values(): for i, iteration in enumerate(loop): extract_values(iteration, path + (i,)) extract_values(top_iteration, ()) db_func = self._code_infos[frame.f_code].db_func exc = exit_info.exc_value if exc: traceback_str = ''.join(traceback.format_exception(type(exc), exc, exit_info.exc_tb)) exception = exception_string(exc) else: traceback_str = exception = None call = Call(id=frame_info.call_id, function=db_func, arguments=frame_info.arguments, return_value=cheap_repr(exit_info.return_value), exception=exception, traceback=traceback_str, data=json.dumps( dict( node_values=node_values, loop_iterations=loop_iterations, type_names=type_registry.names(), num_special_types=type_registry.num_special_types, ), separators=(',', ':') ), start_time=frame_info.start_time) session.add(call) session.commit()
def test_registered_default_repr(self): x = FakeExpensiveReprClass() self.assertEqual(repr(x), 'bad') self.assertTrue( re.match(r'<FakeExpensiveReprClass instance at 0x(.+)>', cheap_repr(x)))
def assert_cheap_repr(self, x, expected_repr): self.assertEqual(cheap_repr(x), expected_repr)