def canSerialize(obj):
  result = False
        
  container_type_tuple = (list, tuple, dict, set, frozenset)
  
  # if object is a container, we need to check its elements for presence of
  # objects that cannot be put inside the zodb
  if isinstance(obj, container_type_tuple):
    if isinstance(obj, dict):
      result_list = []
      for key, value in obj.iteritems():
        result_list.append(canSerialize(key))
        result_list.append(canSerialize(value))
    else:
      result_list = [canSerialize(element) for element in obj]
    return all(result_list)
  # if obj is an object and implements __getstate__, ZODB.serialize can check
  # if we can store it
  elif isinstance(obj, object) and hasattr(obj, '__getstate__'):
    # Need to unwrap the variable, otherwise we get a TypeError, because
    # objects cannot be pickled while inside an acquisition wrapper.
    unwrapped_obj = Acquisition.aq_base(obj)
    writer = ObjectWriter(unwrapped_obj)
    for obj in writer:
      try:
        writer.serialize(obj)
      # Because writer.serialize(obj) relies on the implementation of __getstate__
      # of obj, all errors can happen, so the "except all" is necessary here. 
      except:
        return False
    return True
  else:
    # If cannot serialize object with ZODB.serialize, try with cPickle
    # Only a dump of the object is not enough. Dumping and trying to
    # load it will properly raise errors in all possible situations, 
    # for example: if the user defines a dict with an object of a class 
    # that he created the dump will stil work, but the load will fail. 
    try:
      cPickle.loads(cPickle.dumps(obj))
    # By unknowing reasons, trying to catch cPickle.PicklingError in the "normal"
    # way isn't working. This issue might be related to some weirdness in 
    # pickle/cPickle that is reported in this issue: http://bugs.python.org/issue1457119.
    #
    # So, as a temporary fix, we're investigating the exception's class name as
    # string to be able to identify them.
    # 
    # Even though the issue seems complicated, this quickfix should be 
    # properly rewritten in a better way as soon as possible.
    except Exception as e:
      if type(e).__name__ in ('PicklingError', 'TypeError', 'NameError', 'AttributeError'):
        return False
      else:
        raise e
    else:
      return True
Пример #2
0
def canSerialize(obj):
    result = False

    container_type_tuple = (list, tuple, dict, set, frozenset)

    # if object is a container, we need to check its elements for presence of
    # objects that cannot be put inside the zodb
    if isinstance(obj, container_type_tuple):
        if isinstance(obj, dict):
            result_list = []
            for key, value in obj.iteritems():
                result_list.append(canSerialize(key))
                result_list.append(canSerialize(value))
        else:
            result_list = [canSerialize(element) for element in obj]
        return all(result_list)
    # if obj is an object and implements __getstate__, ZODB.serialize can check
    # if we can store it
    elif isinstance(obj, object) and hasattr(obj, '__getstate__') and hasattr(
            obj, '_p_jar'):
        # Need to unwrap the variable, otherwise we get a TypeError, because
        # objects cannot be pickled while inside an acquisition wrapper.
        unwrapped_obj = Acquisition.aq_base(obj)
        writer = ObjectWriter(unwrapped_obj)
        for obj in writer:
            try:
                writer.serialize(obj)
            # Because writer.serialize(obj) relies on the implementation of __getstate__
            # of obj, all errors can happen, so the "except all" is necessary here.
            except:
                return False
        return True
    else:
        # If cannot serialize object with ZODB.serialize, try with cPickle
        # Only a dump of the object is not enough. Dumping and trying to
        # load it will properly raise errors in all possible situations,
        # for example: if the user defines a dict with an object of a class
        # that he created the dump will stil work, but the load will fail.
        try:
            cPickle.loads(cPickle.dumps(obj))
        # By unknowing reasons, trying to catch cPickle.PicklingError in the "normal"
        # way isn't working. This issue might be related to some weirdness in
        # pickle/cPickle that is reported in this issue: http://bugs.python.org/issue1457119.
        #
        # So, as a temporary fix, we're investigating the exception's class name as
        # string to be able to identify them.
        #
        # Even though the issue seems complicated, this quickfix should be
        # properly rewritten in a better way as soon as possible.
        except (cPickle.PicklingError, TypeError, NameError,
                AttributeError) as e:
            return False
        else:
            return True
Пример #3
0
def register(self, obj):
    """
    Serialize early to inspect PicklingErrors

    Raise any PicklingErrors when the object is added to the
    transaction as opposed to when the transaction is committed.
    Under pdb, for example, this allows inspecting the code that made
    the change resulting in the PicklingError.

    Requires either zope.testrunner or zope.testing which can be included using
    the 'zodb' or 'zodb-testing' extras respectively.
    """
    orig_register(self, obj)

    writer = ObjectWriter(obj)

    # Replace the pickler so that it doesn't set oids
    import cPickle as pickle
    writer._p = pickle.Pickler(writer._file, 1)

    # Try to serialize to raise piclkling errors early
    writer.serialize(obj)