diff --git a/novaclient/openstack/common/jsonutils.py b/novaclient/openstack/common/jsonutils.py deleted file mode 100644 index b08a679c5..000000000 --- a/novaclient/openstack/common/jsonutils.py +++ /dev/null @@ -1,186 +0,0 @@ -# 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 codecs -import datetime -import functools -import inspect -import itertools -import sys - -if sys.version_info < (2, 7): - # On Python <= 2.6, json module is not C boosted, so try to use - # simplejson module if available - try: - import simplejson as json - except ImportError: - import json -else: - import json - -import six -import six.moves.xmlrpc_client as xmlrpclib - -from novaclient.openstack.common import gettextutils -from novaclient.openstack.common import importutils -from novaclient.openstack.common import strutils -from novaclient.openstack.common import timeutils - -netaddr = importutils.try_import("netaddr") - -_nasty_type_tests = [inspect.ismodule, inspect.isclass, inspect.ismethod, - inspect.isfunction, inspect.isgeneratorfunction, - inspect.isgenerator, inspect.istraceback, inspect.isframe, - inspect.iscode, inspect.isbuiltin, inspect.isroutine, - inspect.isabstract] - -_simple_types = (six.string_types + six.integer_types - + (type(None), bool, float)) - - -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 six.iteritems(value)) - 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 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) - - -def dumps(value, default=to_primitive, **kwargs): - return json.dumps(value, default=default, **kwargs) - - -def loads(s, encoding='utf-8'): - return json.loads(strutils.safe_decode(s, encoding)) - - -def load(fp, encoding='utf-8'): - return json.load(codecs.getreader(encoding)(fp)) - - -try: - import anyjson -except ImportError: - pass -else: - anyjson._modules.append((__name__, 'dumps', TypeError, - 'loads', ValueError, 'load')) - anyjson.force_implementation(__name__) diff --git a/novaclient/openstack/common/timeutils.py b/novaclient/openstack/common/timeutils.py deleted file mode 100644 index 52688a026..000000000 --- a/novaclient/openstack/common/timeutils.py +++ /dev/null @@ -1,210 +0,0 @@ -# Copyright 2011 OpenStack Foundation. -# 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. - -""" -Time related utilities and helper functions. -""" - -import calendar -import datetime -import time - -import iso8601 -import six - - -# ISO 8601 extended time format with microseconds -_ISO8601_TIME_FORMAT_SUBSECOND = '%Y-%m-%dT%H:%M:%S.%f' -_ISO8601_TIME_FORMAT = '%Y-%m-%dT%H:%M:%S' -PERFECT_TIME_FORMAT = _ISO8601_TIME_FORMAT_SUBSECOND - - -def isotime(at=None, subsecond=False): - """Stringify time in ISO 8601 format.""" - if not at: - at = utcnow() - st = at.strftime(_ISO8601_TIME_FORMAT - if not subsecond - else _ISO8601_TIME_FORMAT_SUBSECOND) - tz = at.tzinfo.tzname(None) if at.tzinfo else 'UTC' - st += ('Z' if tz == 'UTC' else tz) - return st - - -def parse_isotime(timestr): - """Parse time from ISO 8601 format.""" - try: - return iso8601.parse_date(timestr) - except iso8601.ParseError as e: - raise ValueError(six.text_type(e)) - except TypeError as e: - raise ValueError(six.text_type(e)) - - -def strtime(at=None, fmt=PERFECT_TIME_FORMAT): - """Returns formatted utcnow.""" - if not at: - at = utcnow() - return at.strftime(fmt) - - -def parse_strtime(timestr, fmt=PERFECT_TIME_FORMAT): - """Turn a formatted time back into a datetime.""" - return datetime.datetime.strptime(timestr, fmt) - - -def normalize_time(timestamp): - """Normalize time in arbitrary timezone to UTC naive object.""" - offset = timestamp.utcoffset() - if offset is None: - return timestamp - return timestamp.replace(tzinfo=None) - offset - - -def is_older_than(before, seconds): - """Return True if before is older than seconds.""" - if isinstance(before, six.string_types): - before = parse_strtime(before).replace(tzinfo=None) - else: - before = before.replace(tzinfo=None) - - return utcnow() - before > datetime.timedelta(seconds=seconds) - - -def is_newer_than(after, seconds): - """Return True if after is newer than seconds.""" - if isinstance(after, six.string_types): - after = parse_strtime(after).replace(tzinfo=None) - else: - after = after.replace(tzinfo=None) - - return after - utcnow() > datetime.timedelta(seconds=seconds) - - -def utcnow_ts(): - """Timestamp version of our utcnow function.""" - if utcnow.override_time is None: - # NOTE(kgriffs): This is several times faster - # than going through calendar.timegm(...) - return int(time.time()) - - return calendar.timegm(utcnow().timetuple()) - - -def utcnow(): - """Overridable version of utils.utcnow.""" - if utcnow.override_time: - try: - return utcnow.override_time.pop(0) - except AttributeError: - return utcnow.override_time - return datetime.datetime.utcnow() - - -def iso8601_from_timestamp(timestamp): - """Returns a iso8601 formatted date from timestamp.""" - return isotime(datetime.datetime.utcfromtimestamp(timestamp)) - - -utcnow.override_time = None - - -def set_time_override(override_time=None): - """Overrides utils.utcnow. - - Make it return a constant time or a list thereof, one at a time. - - :param override_time: datetime instance or list thereof. If not - given, defaults to the current UTC time. - """ - utcnow.override_time = override_time or datetime.datetime.utcnow() - - -def advance_time_delta(timedelta): - """Advance overridden time using a datetime.timedelta.""" - assert(not utcnow.override_time is None) - try: - for dt in utcnow.override_time: - dt += timedelta - except TypeError: - utcnow.override_time += timedelta - - -def advance_time_seconds(seconds): - """Advance overridden time by seconds.""" - advance_time_delta(datetime.timedelta(0, seconds)) - - -def clear_time_override(): - """Remove the overridden time.""" - utcnow.override_time = None - - -def marshall_now(now=None): - """Make an rpc-safe datetime with microseconds. - - Note: tzinfo is stripped, but not required for relative times. - """ - if not now: - now = utcnow() - return dict(day=now.day, month=now.month, year=now.year, hour=now.hour, - minute=now.minute, second=now.second, - microsecond=now.microsecond) - - -def unmarshall_time(tyme): - """Unmarshall a datetime dict.""" - return datetime.datetime(day=tyme['day'], - month=tyme['month'], - year=tyme['year'], - hour=tyme['hour'], - minute=tyme['minute'], - second=tyme['second'], - microsecond=tyme['microsecond']) - - -def delta_seconds(before, after): - """Return the difference between two timing objects. - - Compute the difference in seconds between two date, time, or - datetime objects (as a float, to microsecond resolution). - """ - delta = after - before - return total_seconds(delta) - - -def total_seconds(delta): - """Return the total seconds of datetime.timedelta object. - - Compute total seconds of datetime.timedelta, datetime.timedelta - doesn't have method total_seconds in Python2.6, calculate it manually. - """ - try: - return delta.total_seconds() - except AttributeError: - return ((delta.days * 24 * 3600) + delta.seconds + - float(delta.microseconds) / (10 ** 6)) - - -def is_soon(dt, window): - """Determines if time is going to happen in the next window seconds. - - :param dt: the time - :param window: minimum seconds to remain to consider the time not soon - - :return: True if expiration is within the given duration - """ - soon = (utcnow() + datetime.timedelta(seconds=window)) - return normalize_time(dt) <= soon diff --git a/novaclient/tests/fixture_data/floatingips.py b/novaclient/tests/fixture_data/floatingips.py index 5fc6848a7..d73546fb7 100644 --- a/novaclient/tests/fixture_data/floatingips.py +++ b/novaclient/tests/fixture_data/floatingips.py @@ -10,7 +10,8 @@ # License for the specific language governing permissions and limitations # under the License. -from novaclient.openstack.common import jsonutils +from oslo.serialization import jsonutils + from novaclient.tests import fakes from novaclient.tests.fixture_data import base diff --git a/novaclient/tests/fixture_data/hosts.py b/novaclient/tests/fixture_data/hosts.py index babfbec7c..0235117a8 100644 --- a/novaclient/tests/fixture_data/hosts.py +++ b/novaclient/tests/fixture_data/hosts.py @@ -10,9 +10,9 @@ # License for the specific language governing permissions and limitations # under the License. +from oslo.serialization import jsonutils from six.moves.urllib import parse -from novaclient.openstack.common import jsonutils from novaclient.tests.fixture_data import base diff --git a/novaclient/tests/fixture_data/images.py b/novaclient/tests/fixture_data/images.py index 40cfd0c94..9c9ef10f2 100644 --- a/novaclient/tests/fixture_data/images.py +++ b/novaclient/tests/fixture_data/images.py @@ -10,7 +10,8 @@ # License for the specific language governing permissions and limitations # under the License. -from novaclient.openstack.common import jsonutils +from oslo.serialization import jsonutils + from novaclient.tests import fakes from novaclient.tests.fixture_data import base diff --git a/novaclient/tests/fixture_data/keypairs.py b/novaclient/tests/fixture_data/keypairs.py index cc8921beb..97cf24992 100644 --- a/novaclient/tests/fixture_data/keypairs.py +++ b/novaclient/tests/fixture_data/keypairs.py @@ -10,7 +10,8 @@ # License for the specific language governing permissions and limitations # under the License. -from novaclient.openstack.common import jsonutils +from oslo.serialization import jsonutils + from novaclient.tests import fakes from novaclient.tests.fixture_data import base diff --git a/novaclient/tests/fixture_data/networks.py b/novaclient/tests/fixture_data/networks.py index df721b25d..44d7d528a 100644 --- a/novaclient/tests/fixture_data/networks.py +++ b/novaclient/tests/fixture_data/networks.py @@ -10,7 +10,8 @@ # License for the specific language governing permissions and limitations # under the License. -from novaclient.openstack.common import jsonutils +from oslo.serialization import jsonutils + from novaclient.tests.fixture_data import base diff --git a/novaclient/tests/fixture_data/security_group_rules.py b/novaclient/tests/fixture_data/security_group_rules.py index 480c4fc6d..aab4c2456 100644 --- a/novaclient/tests/fixture_data/security_group_rules.py +++ b/novaclient/tests/fixture_data/security_group_rules.py @@ -10,7 +10,8 @@ # License for the specific language governing permissions and limitations # under the License. -from novaclient.openstack.common import jsonutils +from oslo.serialization import jsonutils + from novaclient.tests import fakes from novaclient.tests.fixture_data import base diff --git a/novaclient/tests/fixture_data/security_groups.py b/novaclient/tests/fixture_data/security_groups.py index 7d1fed380..9f2f96b7d 100644 --- a/novaclient/tests/fixture_data/security_groups.py +++ b/novaclient/tests/fixture_data/security_groups.py @@ -10,7 +10,8 @@ # License for the specific language governing permissions and limitations # under the License. -from novaclient.openstack.common import jsonutils +from oslo.serialization import jsonutils + from novaclient.tests import fakes from novaclient.tests.fixture_data import base diff --git a/novaclient/tests/fixture_data/server_groups.py b/novaclient/tests/fixture_data/server_groups.py index 47e307153..6defc895c 100644 --- a/novaclient/tests/fixture_data/server_groups.py +++ b/novaclient/tests/fixture_data/server_groups.py @@ -10,7 +10,8 @@ # License for the specific language governing permissions and limitations # under the License. -from novaclient.openstack.common import jsonutils +from oslo.serialization import jsonutils + from novaclient.tests.fixture_data import base diff --git a/novaclient/tests/fixture_data/servers.py b/novaclient/tests/fixture_data/servers.py index c8f87bf60..4cb3bddda 100644 --- a/novaclient/tests/fixture_data/servers.py +++ b/novaclient/tests/fixture_data/servers.py @@ -10,7 +10,8 @@ # License for the specific language governing permissions and limitations # under the License. -from novaclient.openstack.common import jsonutils +from oslo.serialization import jsonutils + from novaclient.tests import fakes from novaclient.tests.fixture_data import base diff --git a/novaclient/tests/utils.py b/novaclient/tests/utils.py index 036702ec5..a257ac1fa 100644 --- a/novaclient/tests/utils.py +++ b/novaclient/tests/utils.py @@ -14,14 +14,13 @@ import os import fixtures +from oslo.serialization import jsonutils import requests from requests_mock.contrib import fixture as requests_mock_fixture import six import testscenarios import testtools -from novaclient.openstack.common import jsonutils - AUTH_URL = "http://localhost:5002/auth_url" AUTH_URL_V1 = "http://localhost:5002/auth_url/v1.0" AUTH_URL_V2 = "http://localhost:5002/auth_url/v2.0" diff --git a/novaclient/tests/v1_1/test_servers.py b/novaclient/tests/v1_1/test_servers.py index a8a3aeabd..9bd7fddea 100644 --- a/novaclient/tests/v1_1/test_servers.py +++ b/novaclient/tests/v1_1/test_servers.py @@ -13,10 +13,10 @@ # under the License. import mock +from oslo.serialization import jsonutils import six from novaclient import exceptions -from novaclient.openstack.common import jsonutils from novaclient.tests.fixture_data import client from novaclient.tests.fixture_data import floatingips from novaclient.tests.fixture_data import servers as data diff --git a/novaclient/utils.py b/novaclient/utils.py index d6068ba0c..99d91abb2 100644 --- a/novaclient/utils.py +++ b/novaclient/utils.py @@ -17,6 +17,7 @@ import sys import textwrap import uuid +from oslo.serialization import jsonutils from oslo.utils import encodeutils import pkg_resources import prettytable @@ -25,7 +26,6 @@ import six from novaclient import exceptions from novaclient.openstack.common import cliutils from novaclient.openstack.common.gettextutils import _ -from novaclient.openstack.common import jsonutils arg = cliutils.arg diff --git a/openstack-common.conf b/openstack-common.conf index 3842ed9ba..3af93417e 100644 --- a/openstack-common.conf +++ b/openstack-common.conf @@ -5,7 +5,6 @@ module=apiclient module=cliutils module=gettextutils module=install_venv_common -module=jsonutils module=uuidutils # The base module to hold the copy of openstack.common diff --git a/requirements.txt b/requirements.txt index 08de4eb63..266e01732 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,6 +4,7 @@ pbr>=0.6,!=0.7,<1.0 argparse iso8601>=0.1.9 +oslo.serialization>=1.0.0 # Apache-2.0 oslo.utils>=1.0.0 # Apache-2.0 PrettyTable>=0.7,<0.8 requests>=1.2.1,!=2.4.0