From 1d13d3fc08f844945e2898352d3a03f9eedf7b03 Mon Sep 17 00:00:00 2001 From: Shaheed Haque Date: Sat, 29 Sep 2018 21:24:29 +0100 Subject: [PATCH] Use a dict to de-duplicate filenames, and thus reduce the size of the to_dict(). --- src/tblib/__init__.py | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/src/tblib/__init__.py b/src/tblib/__init__.py index 6726fb5..289f01e 100644 --- a/src/tblib/__init__.py +++ b/src/tblib/__init__.py @@ -140,10 +140,19 @@ def __tproxy_handler(self, operation, *args, **kwargs): def to_dict(self): """Convert a Traceback into a dictionary representation""" + # Create a compression dictionary, to be filled as we go, and stuff it + # into the top level. + zipper = {} + result = self._to_compressed_dict(zipper) + result['zip'] = zipper + return result + + def _to_compressed_dict(self, zipper): + """Convert a Traceback into a dictionary with optimised filename storage""" if self.tb_next is None: tb_next = None else: - tb_next = self.tb_next.to_dict() + tb_next = self.tb_next._to_compressed_dict(zipper) code = { 'co_filename': self.tb_frame.f_code.co_filename, @@ -153,6 +162,9 @@ def to_dict(self): 'f_globals': self.tb_frame.f_globals, 'f_code': code, } + + # Update the filename entries with integers. + code['co_filename'] = zipper.setdefault(code['co_filename'], len(zipper)) return { 'tb_frame': frame, 'tb_lineno': self.tb_lineno, @@ -161,11 +173,20 @@ def to_dict(self): @classmethod def from_dict(cls, dct): + # Have zip keyed by strings was ideal for JSON transport, now we need + # to switch to doing lookups the other way around. + zipper = {v: k for k, v in dct['zip'].items()} + return cls._from_compressed_dict(dct, zipper) + + @classmethod + def _from_compressed_dict(cls, dct, zipper): if dct['tb_next']: - tb_next = cls.from_dict(dct['tb_next']) + tb_next = cls._from_compressed_dict(dct['tb_next'], zipper) else: tb_next = None + # Update the filename entries with strings. + dct['tb_frame']['f_code']['co_filename'] = zipper[dct['tb_frame']['f_code']['co_filename']] code = _AttrDict( co_filename=dct['tb_frame']['f_code']['co_filename'], co_name=dct['tb_frame']['f_code']['co_name'],