1

I want to hide some (private) attributes when pickling an object instance (to send to a json-api endpoint). I've added a __getstate__ function to that effect, but the side effect is that deepcopy also makes use of __getstate__. I don't want to exclude any attributes when deepcopy-ing an instance, is there a way to differentiate between calling functions here?

class LevelMixin(object):

def __init___(self...):
    ....

def __getstate__(self):
    """
    If pickleable hide all private and weak refs.
    """

    if not getattr(self, '_unpickleable', True):

        __state = self.__dict__.copy()
        keep_private = ['_unpickleable', 'unpickleable']
        state = {}

        for k, v in __state.items():
            if v is not None and v != "None" and k not in keep_private and not callable(v):
                if k.startswith('_') and not k.startswith('__'):
                    state[k[1:]] = v  # if key starts with single underscore, remove it
                else:
                    state[k] = v
    else:
        state = self.__dict__.copy()
    return state

Inspecting the stack tells me when either 'deepcopy' or '_flatten_obj_instance' are the calling function, but I know it's not good practise to check for these in production code. Any ideas as to how I can avoid this code for deepcopy, but make use of it in jsonpickle?

Liz
  • 1,421
  • 5
  • 21
  • 39

1 Answers1

1

In case this helps anyone, I decided to register more-verbose custom handlers and be explicit about the representation of the data upon de/serialization, along the lines of:

import jsonpickle.handlers

@jsonpickle.handlers.register(LevelMixin, base=True)
class LevelMixinHandler(jsonpickle.handlers.BaseHandler):
    """Custom jsonpickle handler for LevelMixin"""

    def flatten(self, obj, data):
        data['name'] = obj.name
        data['type'] = obj.type
        data['pretty_name'] = obj.pretty_name
        data['description'] = obj.description
        ...
        return data

    def restore(self, obj):
        pass
Liz
  • 1,421
  • 5
  • 21
  • 39