AttributeError flattening an object with string '__slots__' #66

Closed
jaraco opened this Issue Mar 14, 2014 · 1 comment

Comments

Projects
None yet
1 participant
@jaraco
Contributor

jaraco commented Mar 14, 2014

Python allows __slots__ to be a string, list, or other iterable.

If __slots__ is a string, jsonpickle treats it as an iterable and fails iterating over the characters of the string. Consider this simple test using pymongo:

import jsonpickle
import bson
oid = bson.ObjectId()
jsonpickle.encode(oid)

Produces this traceback:

Traceback (most recent call last):
  File "C:\Users\jaraco\projects\public\jsonpickle\test-oid.py", line 4, in <module>
    jsonpickle.encode(oid)
  File "C:\Users\jaraco\projects\public\jsonpickle\jsonpickle\__init__.py", line 135, in encode
    max_depth=max_depth)
  File "C:\Users\jaraco\projects\public\jsonpickle\jsonpickle\pickler.py", line 29, in encode
    return backend.encode(context.flatten(value, reset=reset))
  File "C:\Users\jaraco\projects\public\jsonpickle\jsonpickle\pickler.py", line 121, in flatten
    return self._flatten(obj)
  File "C:\Users\jaraco\projects\public\jsonpickle\jsonpickle\pickler.py", line 125, in _flatten
    return self._pop(self._flatten_obj(obj))
  File "C:\Users\jaraco\projects\public\jsonpickle\jsonpickle\pickler.py", line 137, in _flatten_obj
    return flatten_func(obj)
  File "C:\Users\jaraco\projects\public\jsonpickle\jsonpickle\pickler.py", line 185, in _ref_obj_instance
    return self._flatten_obj_instance(obj)
  File "C:\Users\jaraco\projects\public\jsonpickle\jsonpickle\pickler.py", line 246, in _flatten_obj_instance
    return self._flatten_newstyle_with_slots(obj, data)
  File "C:\Users\jaraco\projects\public\jsonpickle\jsonpickle\pickler.py", line 268, in _flatten_newstyle_with_slots
    self._flatten_key_value_pair(k, getattr(obj, k), data)
AttributeError: 'ObjectId' object has no attribute '_'

Because oid.__slots__ == '__id', when jsonpickle tries to iterate over slots, it first looks for the attribute '_' and fails.

I'll prepare a test and fix for this.

I note also, though there is a harder problem of supporting iterables in general. If the iterable for __slots__ is already consumed, __slots__ is not helpful in ascertaining the slots used by the class.. but that's a separate issue.

@davvid davvid closed this in 8298efb Aug 23, 2014

@jaraco

This comment has been minimized.

Show comment
Hide comment
@jaraco

jaraco Aug 23, 2014

Contributor

Thanks for the fix.

Contributor

jaraco commented Aug 23, 2014

Thanks for the fix.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment