Merge "Add a custom JSONEncoder"

This commit is contained in:
Zuul 2019-02-13 16:36:00 +00:00 committed by Gerrit Code Review
commit 48cb644dcc
8 changed files with 77 additions and 46 deletions

35
cloudkitty/json_utils.py Normal file
View File

@ -0,0 +1,35 @@
# Copyright 2019 Objectif Libre
#
# 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.
#
import datetime
import decimal
import functools
import json
from cloudkitty import utils as ck_utils
class CloudkittyJSONEncoder(json.JSONEncoder):
"""Cloudkitty custom json encoder."""
def default(self, obj):
if isinstance(obj, decimal.Decimal):
return float(obj)
elif isinstance(obj, datetime.datetime):
return ck_utils.dt2iso(obj)
return super(CloudkittyJSONEncoder, self).default(obj)
dumps = functools.partial(json.dumps, cls=CloudkittyJSONEncoder)
loads = json.loads

View File

@ -15,10 +15,8 @@
#
# @author: Stéphane Albert
#
import decimal
import json
from cloudkitty.db import api
from cloudkitty import json_utils as json
class StateManager(object):
@ -94,14 +92,6 @@ class StateManager(object):
return self._metadata
class DecimalJSONEncoder(json.JSONEncoder):
"""Wrapper class to handle decimal.Decimal objects in json.dumps()."""
def default(self, obj):
if isinstance(obj, decimal.Decimal):
return float(obj)
return super(DecimalJSONEncoder, self).default(obj)
class DBStateManager(object):
def __init__(self, user_id, report_type, distributed=False):
self._state_name = self._gen_name(report_type, user_id)
@ -132,5 +122,4 @@ class DBStateManager(object):
def set_metadata(self, metadata):
"""Set metadata attached to the state."""
self._db.set_metadata(self._state_name,
json.dumps(metadata, cls=DecimalJSONEncoder))
self._db.set_metadata(self._state_name, json.dumps(metadata))

View File

@ -17,7 +17,6 @@
#
import datetime
import decimal
import json
from gnocchiclient import client as gclient
from gnocchiclient import exceptions as gexceptions
@ -28,6 +27,7 @@ from oslo_utils import uuidutils
import six
from cloudkitty.collector import validate_conf
from cloudkitty import json_utils as json
from cloudkitty.storage.v1.hybrid.backends import BaseHybridBackend
import cloudkitty.utils as ck_utils
@ -67,14 +67,6 @@ RESOURCE_TYPE_NAME_ROOT = 'rating_service_'
METADATA_NAME_ROOT = 'ckmeta_'
class DecimalJSONEncoder(json.JSONEncoder):
"""Wrapper class to handle decimal.Decimal objects in json.dumps()."""
def default(self, obj):
if isinstance(obj, decimal.Decimal):
return float(obj)
return super(DecimalJSONEncoder, self).default(obj)
class UnknownResourceType(Exception):
"""Exception raised when an unknown resource type is encountered"""

View File

@ -16,12 +16,12 @@
# @author: Stéphane Albert
#
import decimal
import json
from oslo_db.sqlalchemy import utils
import sqlalchemy
from cloudkitty import db
from cloudkitty import json_utils as json
from cloudkitty.storage import NoTimeFrame
from cloudkitty.storage import v1 as storage
from cloudkitty.storage.v1.sqlalchemy import migration
@ -29,14 +29,6 @@ from cloudkitty.storage.v1.sqlalchemy import models
from cloudkitty import utils as ck_utils
class DecimalJSONEncoder(json.JSONEncoder):
"""Wrapper class to handle decimal.Decimal objects in json.dumps()."""
def default(self, obj):
if isinstance(obj, decimal.Decimal):
return float(obj)
return super(DecimalJSONEncoder, self).default(obj)
class SQLAlchemyStorage(storage.BaseStorage):
"""SQLAlchemy Storage Backend
@ -185,7 +177,7 @@ class SQLAlchemyStorage(storage.BaseStorage):
rate = rating_dict.get('price')
if not rate:
rate = decimal.Decimal(0)
desc = json.dumps(frame['desc'], cls=DecimalJSONEncoder)
desc = json.dumps(frame['desc'])
self.add_time_frame(begin=self.usage_start_dt.get(tenant_id),
end=self.usage_end_dt.get(tenant_id),
tenant_id=tenant_id,

View File

@ -15,14 +15,14 @@
#
# @author: Stéphane Albert
#
import json
from oslo_db.sqlalchemy import models
import sqlalchemy
from sqlalchemy.ext import declarative
from cloudkitty import json_utils as json
from cloudkitty import utils as ck_utils
Base = declarative.declarative_base()

View File

@ -0,0 +1,30 @@
# Copyright 2019 Objectif Libre
#
# 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.
#
import datetime
import decimal
from cloudkitty import json_utils as json
from cloudkitty import tests
class JSONEncoderTest(tests.TestCase):
def test_encode_decimal(self):
obj = {'nb': decimal.Decimal(42)}
self.assertEqual(json.dumps(obj), '{"nb": 42.0}')
def test_encode_datetime(self):
obj = {'date': datetime.datetime(2019, 1, 1)}
self.assertEqual(json.dumps(obj), '{"date": "2019-01-01T00:00:00Z"}')

View File

@ -15,20 +15,12 @@
#
# @author: Stéphane Albert
#
import decimal
import json
import os
from cloudkitty import json_utils as json
from cloudkitty import writer
class DecimalEncoder(json.JSONEncoder):
def default(self, o):
if isinstance(o, decimal.Decimal):
return float(o)
return super(DecimalEncoder, self).default(o)
class OSRFBackend(writer.BaseReportWriter):
"""OpenStack Report Format Writer:
@ -59,7 +51,7 @@ class OSRFBackend(writer.BaseReportWriter):
def _write_total(self):
total = {'total': self.total}
self._report.write(json.dumps(total, cls=DecimalEncoder))
self._report.write(json.dumps(total))
self._report.write(']')
self._report.flush()
@ -96,6 +88,6 @@ class OSRFBackend(writer.BaseReportWriter):
'end': self.usage_end_dt.isoformat()}
data['usage'] = self._usage_data
self._report.write(json.dumps(data, cls=DecimalEncoder))
self._report.write(json.dumps(data))
self._report.write(', ')
self._report.flush()

View File

@ -20,11 +20,12 @@ import calendar
import copy
import csv
import datetime
import json
import random
import sys
import uuid
from cloudkitty import json_utils as json
COMPUTE = {
"type": "compute",