Horizon should use openstack.common.jsonutils

Implements blueprint use-common-jsonutils

1. Edit openstack-common.conf and import horizon/openstack/common/jsonutils.py
2. Remove json package imports and replace with jsonutils

Change-Id: I3b8e53f484eef8273fcb578474932f9d4e789881
This commit is contained in:
Zhongyue Luo 2012-06-07 16:57:58 +08:00
parent 2bae084412
commit da9ee69208
4 changed files with 149 additions and 10 deletions

View File

@ -18,14 +18,13 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
import json
from django import forms from django import forms
from django.utils.text import normalize_newlines from django.utils.text import normalize_newlines
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
from horizon import api from horizon import api
from horizon import exceptions from horizon import exceptions
from horizon.openstack.common import jsonutils
from horizon import workflows from horizon import workflows
@ -268,9 +267,9 @@ class SetInstanceDetailsAction(workflows.Action):
extra = {} extra = {}
try: try:
extra['usages'] = api.nova.tenant_quota_usages(self.request) extra['usages'] = api.nova.tenant_quota_usages(self.request)
extra['usages_json'] = json.dumps(extra['usages']) extra['usages_json'] = jsonutils.dumps(extra['usages'])
flavors = json.dumps([f._info flavors = jsonutils.dumps([f._info for f in
for f in api.nova.flavor_list(self.request)]) api.nova.flavor_list(self.request)])
extra['flavors'] = flavors extra['flavors'] = flavors
except: except:
exceptions.handle(self.request) exceptions.handle(self.request)

View File

@ -0,0 +1,140 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2010 United States Government as represented by the
# Administrator of the National Aeronautics and Space Administration.
# Copyright 2011 Justin Santa Barbara
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
'''
JSON related utilities.
This module provides a few things:
1) A handy function for getting an object down to something that can be
JSON serialized. See to_primitive().
2) Wrappers around loads() and dumps(). The dumps() wrapper will
automatically use to_primitive() for you if needed.
3) This sets up anyjson to use the loads() and dumps() wrappers if anyjson
is available.
'''
import datetime
import inspect
import itertools
import json
import xmlrpclib
def to_primitive(value, convert_instances=False, level=0):
"""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.
"""
nasty = [inspect.ismodule, inspect.isclass, inspect.ismethod,
inspect.isfunction, inspect.isgeneratorfunction,
inspect.isgenerator, inspect.istraceback, inspect.isframe,
inspect.iscode, inspect.isbuiltin, inspect.isroutine,
inspect.isabstract]
for test in nasty:
if test(value):
return unicode(value)
# value of itertools.count doesn't get caught by inspects
# above and results in infinite loop when list(value) is called.
if type(value) == itertools.count:
return unicode(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 > 3:
return '?'
# The try block may not be necessary after the class check above,
# but just in case ...
try:
# 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 isinstance(value, xmlrpclib.DateTime):
value = datetime.datetime(*tuple(value.timetuple())[:6])
if isinstance(value, (list, tuple)):
o = []
for v in value:
o.append(to_primitive(v, convert_instances=convert_instances,
level=level))
return o
elif isinstance(value, dict):
o = {}
for k, v in value.iteritems():
o[k] = to_primitive(v, convert_instances=convert_instances,
level=level)
return o
elif isinstance(value, datetime.datetime):
return str(value)
elif hasattr(value, 'iteritems'):
return to_primitive(dict(value.iteritems()),
convert_instances=convert_instances,
level=level)
elif hasattr(value, '__iter__'):
return to_primitive(list(value), level)
elif convert_instances and hasattr(value, '__dict__'):
# Likely an instance of something. Watch for cycles.
# Ignore class member vars.
return to_primitive(value.__dict__,
convert_instances=convert_instances,
level=level + 1)
else:
return value
except TypeError, e:
# Class objects are tricky since they may define something like
# __iter__ defined but it isn't callable as list().
return unicode(value)
def dumps(value, default=to_primitive, **kwargs):
return json.dumps(value, default=default, **kwargs)
def loads(s):
return json.loads(s)
try:
import anyjson
except ImportError:
pass
else:
anyjson._modules.append((__name__, 'dumps', TypeError,
'loads', ValueError))
anyjson.force_implementation(__name__)

View File

@ -12,7 +12,7 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
import json from horizon.openstack.common import jsonutils
from novaclient.v1_1 import (flavors, keypairs, servers, volumes, quotas, from novaclient.v1_1 import (flavors, keypairs, servers, volumes, quotas,
floating_ips, usage, certs, floating_ips, usage, certs,
@ -246,12 +246,12 @@ def data(TEST):
"image_id": TEST.images.first().id, "image_id": TEST.images.first().id,
"key_name": keypair.name} "key_name": keypair.name}
server_1 = servers.Server(servers.ServerManager(None), server_1 = servers.Server(servers.ServerManager(None),
json.loads(SERVER_DATA % vals)['server']) jsonutils.loads(SERVER_DATA % vals)['server'])
vals.update({"name": "server_2", vals.update({"name": "server_2",
"status": "BUILD", "status": "BUILD",
"server_id": "2"}) "server_id": "2"})
server_2 = servers.Server(servers.ServerManager(None), server_2 = servers.Server(servers.ServerManager(None),
json.loads(SERVER_DATA % vals)['server']) jsonutils.loads(SERVER_DATA % vals)['server'])
TEST.servers.add(server_1, server_2) TEST.servers.add(server_1, server_2)
# VNC Console Data # VNC Console Data
@ -279,7 +279,7 @@ def data(TEST):
"flavor_disk": flavor_1.disk, "flavor_disk": flavor_1.disk,
"flavor_ram": flavor_1.ram} "flavor_ram": flavor_1.ram}
usage_obj = usage.Usage(usage.UsageManager(None), usage_obj = usage.Usage(usage.UsageManager(None),
json.loads(USAGE_DATA % usage_vals)) jsonutils.loads(USAGE_DATA % usage_vals))
TEST.usages.add(usage_obj) TEST.usages.add(usage_obj)
volume_snapshot = vol_snaps.Snapshot(vol_snaps.SnapshotManager(None), volume_snapshot = vol_snaps.Snapshot(vol_snaps.SnapshotManager(None),

View File

@ -1,7 +1,7 @@
[DEFAULT] [DEFAULT]
# The list of modules to copy from openstack-common # The list of modules to copy from openstack-common
modules=setup modules=jsonutils,setup
# The base module to hold the copy of openstack.common # The base module to hold the copy of openstack.common
base=horizon base=horizon