¡@

Home 

OpenStack Study: jsonutils.py

OpenStack Index

**** CubicPower OpenStack Study ****

def to_primitive(value, convert_instances=False, convert_datetime=True,

                 level=0, max_depth=3):

    """Convert a complex object into primitives.

    Handy for JSON serialization. We can optionally handle instances,

    but since this is a recursive function, we could have cyclical

    data structures.

    To handle cyclical data structures we could track the actual objects

    visited in a set, but not all objects are hashable. Instead we just

    track the depth of the object inspections and don't go too deep.

    Therefore, convert_instances=True is lossy ... be aware.

    """

    # handle obvious types first - order of basic types determined by running

    # full tests on nova project, resulting in the following counts:

    # 572754 

    # 460353 

    # 379632 

    # 274610 

    # 199918 

    # 114200 

    #  51817 

    #  26164 

    #   6491 

    #    283 

    #     19 

    if isinstance(value, _simple_types):

        return value

    if isinstance(value, datetime.datetime):

        if convert_datetime:

            return timeutils.strtime(value)

        else:

            return value

    # value of itertools.count doesn't get caught by nasty_type_tests

    # and results in infinite loop when list(value) is called.

    if type(value) == itertools.count:

        return six.text_type(value)

    # FIXME(vish): Workaround for LP bug 852095. Without this workaround,

    #              tests that raise an exception in a mocked method that

    #              has a @wrap_exception with a notifier will fail. If

    #              we up the dependency to 0.5.4 (when it is released) we

    #              can remove this workaround.

    if getattr(value, '__module__', None) == 'mox':

        return 'mock'

    if level > max_depth:

        return '?'

    # The try block may not be necessary after the class check above,

    # but just in case ...

    try:

        recursive = functools.partial(to_primitive,

                                      convert_instances=convert_instances,

                                      convert_datetime=convert_datetime,

                                      level=level,

                                      max_depth=max_depth)

        if isinstance(value, dict):

            return dict((k, recursive(v)) for k, v in value.iteritems())

        elif isinstance(value, (list, tuple)):

            return [recursive(lv) for lv in value]

        # It's not clear why xmlrpclib created their own DateTime type, but

        # for our purposes, make it a datetime type which is explicitly

        # handled

        if xmlrpclib and isinstance(value, xmlrpclib.DateTime):

            value = datetime.datetime(*tuple(value.timetuple())[:6])

        if convert_datetime and isinstance(value, datetime.datetime):

            return timeutils.strtime(value)

        elif isinstance(value, gettextutils.Message):

            return value.data

        elif hasattr(value, 'iteritems'):

            return recursive(dict(value.iteritems()), level=level + 1)

        elif hasattr(value, '__iter__'):

            return recursive(list(value))

        elif convert_instances and hasattr(value, '__dict__'):

            # Likely an instance of something. Watch for cycles.

            # Ignore class member vars.

            return recursive(value.__dict__, level=level + 1)

        elif netaddr and isinstance(value, netaddr.IPAddress):

            return six.text_type(value)

        else:

            if any(test(value) for test in _nasty_type_tests):

                return six.text_type(value)

            return value

    except TypeError:

        # Class objects are tricky since they may define something like

        # __iter__ defined but it isn't callable as list().

        return six.text_type(value)

**** CubicPower OpenStack Study ****

def dumps(value, default=to_primitive, **kwargs):

    return json.dumps(value, default=default, **kwargs)

**** CubicPower OpenStack Study ****

def loads(s):

    return json.loads(s)

**** CubicPower OpenStack Study ****

def load(s):

    return json.load(s)

try:

    import anyjson

except ImportError:

    pass

else:

    anyjson._modules.append((__name__, 'dumps', TypeError,

                                       'loads', ValueError, 'load'))

    anyjson.force_implementation(__name__)